[{"content":" TL;DR: In this session we gave Claude Code a descriptive natural-language prompt and, using the Hexago MCP server, it generated the complete scaffolding for a Go project with hexagonal architecture. We then implemented all the business logic layer by layer until we had a working REST API with PostgreSQL, migrations, and a CLI command to manage them.\nThe project: Family Pantry API A backend API to manage a family pantry. Products are identified by their EAN-13 barcode. The system must:\nMaintain a product catalog with categories. Record stock entries and exits (movements). Validate that stock never goes negative. Generate stock reports and low-stock alerts. Pre-requisites Before start generating the project we needed to do some tasks\nCreate the project folder mkdir pantry cd pantry Register the MCP. For these tests I was registering it as per project, but you can register it globally if you like, just check the documentation about it. This command created a .mcp.json file in the root of the folder. claude mcp add --scope project hexago -- hexago mcp Copied the initial prompt into a file, pantry-init-prompt-natural-en.md in this case. # Family Pantry API — Go Project with Hexagonal Architecture You have access to the **Hexago** MCP server, a scaffolding CLI for Go projects with hexagonal architecture (Ports \u0026amp; Adapters). Use it to generate the complete structure for the project described below. Work in order and validate the architecture at the end. --- ## Project Context A backend API to manage a **family pantry**. Products come from purchases at wholesale stores and are identified by their **EAN-13** barcode. The system must maintain a product catalog and track their movement (stock entries and exits). **Target directory:** `/home/pato/go/src/github.com/padiazg/tmp/pantry` --- ## 1. Initialization Create a new project named `pantry` with Go module `github.com/padiazg/pantry`. Use **Chi** as the HTTP framework. The project is a standard HTTP server. Include support for Docker, database migrations, and observability (health checks / metrics). --- ## 2. Domain ### Entities **Product** — an item stored in the pantry. Fields: `ean13` (string, natural key), `name`, `description`, `unit` (string — e.g. \u0026#34;kg\u0026#34;, \u0026#34;liters\u0026#34;, \u0026#34;units\u0026#34;), `minStock` (float64), `currentStock` (float64), `categoryID` (string), `active` (bool), `createdAt` and `updatedAt` (time.Time). **Category** — a grouping of products. Fields: `id` (string), `name`, `description` (string), `createdAt` (time.Time). **Movement** — a record of a stock entry or exit. Fields: `id` (string), `productEan13` (string), `type` (string — see value object), `quantity` (float64), `reason`, `notes`, `createdBy` (string), `createdAt` (time.Time). ### Value Objects - **MovementType** — represents the movement type: `\u0026#34;in\u0026#34;` (entry) or `\u0026#34;out\u0026#34;` (exit). Must be implemented as typed constants in the domain. - **StockLevel** — a quantity with positive-value validation (\u0026gt; 0). - **EAN13** — a 13-digit barcode. Must validate that the check digit is correct according to the standard GS1 algorithm. --- ## 3. Business Services Generate the following services in the business logic layer: - **ManageProduct** — create, update, and activate/deactivate products. - **GetProduct** — fetch a product by EAN-13 and list products with filters. - **ManageCategory** — create and update categories. - **RecordMovement** — record a stock entry or exit, enforcing business rules. - **GetMovements** — query movement history with optional filters. - **GetStockReport** — generate a current stock summary with low-stock alerts. --- ## 4. Adapters ### Output — Database Repositories Generate a repository for each entity: `ProductRepository`, `CategoryRepository`, and `MovementRepository`. All are secondary adapters of type database. ### Input — HTTP Handlers Generate an HTTP handler for each resource: `ProductHandler`, `CategoryHandler`, and `MovementHandler`. These are primary adapters. --- ## 5. Migrations Create migrations with the following names, in this order: 1. `create_categories_table` 2. `create_products_table` 3. `create_movements_table` 4. `add_stock_indexes` The reference schema to implement them is: ```sql CREATE TABLE categories ( id VARCHAR(36) PRIMARY KEY, name VARCHAR(100) NOT NULL UNIQUE, description TEXT, created_at TIMESTAMP NOT NULL DEFAULT NOW() ); CREATE TABLE products ( ean13 CHAR(13) PRIMARY KEY, name VARCHAR(200) NOT NULL, description TEXT, unit VARCHAR(30) NOT NULL, min_stock DECIMAL(10,3) NOT NULL DEFAULT 0, current_stock DECIMAL(10,3) NOT NULL DEFAULT 0, category_id VARCHAR(36) REFERENCES categories(id), active BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMP NOT NULL DEFAULT NOW(), updated_at TIMESTAMP NOT NULL DEFAULT NOW() ); CREATE TABLE movements ( id VARCHAR(36) PRIMARY KEY, product_ean13 CHAR(13) NOT NULL REFERENCES products(ean13), type VARCHAR(3) NOT NULL CHECK (type IN (\u0026#39;in\u0026#39;, \u0026#39;out\u0026#39;)), quantity DECIMAL(10,3) NOT NULL CHECK (quantity \u0026gt; 0), reason VARCHAR(200), notes TEXT, created_by VARCHAR(100), created_at TIMESTAMP NOT NULL DEFAULT NOW() ); CREATE INDEX idx_movements_product ON movements(product_ean13); CREATE INDEX idx_movements_created ON movements(created_at); CREATE INDEX idx_products_category ON products(category_id); CREATE INDEX idx_products_active ON products(active); ``` ```` --- ## 6. Infrastructure Generate the following support tools: - A **validator** named `PantryValidator`. - A **mapper** named `ProductMapper`. - A **mapper** named `MovementMapper`. --- ## 7. Validation Once all components are generated, verify that the architecture is correct and that there are no dependency violations between layers. --- ## 8. REST API (reference for handler implementation) ### Categories ``` GET /api/v1/categories # list all POST /api/v1/categories # create GET /api/v1/categories/{id} # get by ID PUT /api/v1/categories/{id} # update ``` ### Products ``` GET /api/v1/products # list (?category=\u0026amp;active=\u0026amp;low_stock=) POST /api/v1/products # create GET /api/v1/products/{ean13} # get by EAN-13 PUT /api/v1/products/{ean13} # update DELETE /api/v1/products/{ean13} # deactivate (soft delete) GET /api/v1/products/{ean13}/stock # current stock + minimum level GET /api/v1/products/{ean13}/movements # product movement history ``` ### Movements ``` GET /api/v1/movements # history (?ean13=\u0026amp;type=\u0026amp;from=\u0026amp;to=) POST /api/v1/movements # record a movement (in/out) GET /api/v1/movements/{id} # movement detail ``` ### Reports ``` GET /api/v1/reports/stock # current stock summary GET /api/v1/reports/low-stock # products below minimum ``` --- ## 9. Business Rules 1. **Non-negative stock**: when recording an exit (`out`), reject if `currentStock - quantity \u0026lt; 0`. 2. **Atomic stock update**: record the `Movement` and update `Product.currentStock` in the same database transaction. 3. **Soft delete**: deactivating a product sets `active = false`; the record is never deleted. 4. **Low-stock alert**: a product is low on stock when `currentStock \u0026lt;= minStock`. 5. **EAN-13 validation**: verify that the code has 13 digits and that the check digit is correct (GS1 algorithm) before persisting any product or movement. 6. **Movement IDs as UUID v4**: generated in the service layer, not delegated to the database. --- ## 10. Technology Stack | Component | Library | |-------------|------------------------------------------| | HTTP | `github.com/go-chi/chi/v5` | | Database | PostgreSQL + `github.com/jmoiron/sqlx` | | Migrations | `github.com/golang-migrate/migrate` | | UUID | `github.com/google/uuid` | | Config | `github.com/spf13/viper` (already included) | | Validation | `github.com/go-playground/validator/v10` | ## 11. Environment Variables ```env PANTRY_SERVER_PORT=8080 PANTRY_DATABASE_URL=postgres://user:pass@localhost:5432/pantry?sslmode=disable PANTRY_LOG_LEVEL=info PANTRY_LOG_FORMAT=json ``` --- When the scaffolding is complete, let me know and we\u0026#39;ll start implementing the business logic layer by layer. Session 1 — Scaffolding with Hexago MCP I prompted Claude Code to follow the instruction from the file we just created\n────────────────────────────────────────────────────────────────────────────────── ❯ follow the instructions in pantry-init-prompt-natural-en.md ────────────────────────────────────────────────────────────────────────────────── Claude Code read the file and used the Hexago MCP server to generate the entire structure in order:\n1. Project initialization hexago_init name: pantry module: github.com/padiazg/pantry framework: chi project_type: http-server with_docker: true with_migrations: true with_observability: true This generated: main.go, cmd/root.go, Dockerfile, compose.yaml, Makefile, pkg/logger/, pkg/server/, internal/config/, internal/observability/ and the base folder structure.\n2. Domain entities hexago_add_domain_entity name: Product fields: ean13:string,name:string,... hexago_add_domain_entity name: Category fields: id:string,name:string,... hexago_add_domain_entity name: Movement fields: id:string,productEan13:string,... 3. Value objects hexago_add_domain_valueobject name: EAN13 fields: value:string hexago_add_domain_valueobject name: MovementType fields: value:string hexago_add_domain_valueobject name: StockLevel fields: value:float64 4. Business services hexago_add_service name: ManageProduct hexago_add_service name: GetProduct hexago_add_service name: ManageCategory hexago_add_service name: RecordMovement hexago_add_service name: GetMovements hexago_add_service name: GetStockReport 5. Secondary adapters (Repositories) hexago_add_adapter direction: secondary adapter_type: database name: ProductRepository hexago_add_adapter direction: secondary adapter_type: database name: CategoryRepository hexago_add_adapter direction: secondary adapter_type: database name: MovementRepository 6. Primary adapters (HTTP Handlers) hexago_add_adapter direction: primary adapter_type: http name: ProductHandler hexago_add_adapter direction: primary adapter_type: http name: CategoryHandler hexago_add_adapter direction: primary adapter_type: http name: MovementHandler 7. SQL migrations hexago_add_migration name: create_categories_table migration_type: sql hexago_add_migration name: create_products_table migration_type: sql hexago_add_migration name: create_movements_table migration_type: sql hexago_add_migration name: add_stock_indexes migration_type: sql The .up.sql files were filled in with the schema from the spec:\n-- 000001_create_categories_table.up.sql CREATE TABLE categories ( id VARCHAR(36) PRIMARY KEY, name VARCHAR(100) NOT NULL UNIQUE, description TEXT, created_at TIMESTAMP NOT NULL DEFAULT NOW() ); -- 000002_create_products_table.up.sql CREATE TABLE products ( ean13 CHAR(13) PRIMARY KEY, name VARCHAR(200) NOT NULL, description TEXT, unit VARCHAR(30) NOT NULL, min_stock DECIMAL(10,3) NOT NULL DEFAULT 0, current_stock DECIMAL(10,3) NOT NULL DEFAULT 0, category_id VARCHAR(36) REFERENCES categories(id), active BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMP NOT NULL DEFAULT NOW(), updated_at TIMESTAMP NOT NULL DEFAULT NOW() ); -- 000003_create_movements_table.up.sql CREATE TABLE movements ( id VARCHAR(36) PRIMARY KEY, product_ean13 CHAR(13) NOT NULL REFERENCES products(ean13), type VARCHAR(3) NOT NULL CHECK (type IN (\u0026#39;in\u0026#39;, \u0026#39;out\u0026#39;)), quantity DECIMAL(10,3) NOT NULL CHECK (quantity \u0026gt; 0), reason VARCHAR(200), notes TEXT, created_by VARCHAR(100), created_at TIMESTAMP NOT NULL DEFAULT NOW() ); -- 000004_add_stock_indexes.up.sql CREATE INDEX idx_movements_product ON movements(product_ean13); CREATE INDEX idx_movements_created ON movements(created_at); CREATE INDEX idx_products_category ON products(category_id); CREATE INDEX idx_products_active ON products(active); 8. Infrastructure hexago_add_tool tool_type: validator name: PantryValidator hexago_add_tool tool_type: mapper name: ProductMapper hexago_add_tool tool_type: mapper name: MovementMapper 9. Architecture validation hexago_validate Result: 11/11 checks passed ✓\n✓ Domain layer has no external dependencies ✓ Services only depend on domain interfaces ✓ Adapters depend on domain, not on each other ✓ No circular dependencies ... (8 more checks) Session 2 — Layer-by-layer implementation Now that the scaffolding was completed we asked to implement the bussiness logic. Here is where Claude needs to fill the gaps and construct around the scaffolding. This is where the created structure and project validation feature from our tool becomes valuable by forcing the generator to stay within the established limits.\nInfrastructure - Validator: PantryValidator - Mappers: ProductMapper, MovementMapper Architecture validation: 11/11 checks passed — no dependency violations between layers. Ready to start implementing the business logic layer by layer. Where would you like to begin? ✻ Sautéed for 1m 52s ────────────────────────────────────────────────────────────────────────────────── ❯ implement the business logic layer by layer ────────────────────────────────────────────────────────────────────────────────── With the structure generated, Claude Code implemented the real logic, starting from the inside (domain) outward (HTTP).\nValue objects EAN13 with GS1 validation (check digit algorithm):\n// internal/core/domain/e_a_n13.go type EAN13 struct{ Value string } func NewEAN13(code string) (EAN13, error) { v := EAN13{Value: code} return v, v.Validate() } func (v EAN13) Validate() error { if len(v.Value) != 13 { return fmt.Errorf(\u0026#34;EAN-13 must be 13 digits, got %d\u0026#34;, len(v.Value)) } for _, c := range v.Value { if c \u0026lt; \u0026#39;0\u0026#39; || c \u0026gt; \u0026#39;9\u0026#39; { return fmt.Errorf(\u0026#34;EAN-13 must contain only digits\u0026#34;) } } // GS1 check digit: alternating weights 1/3 on first 12 digits sum := 0 for i := 0; i \u0026lt; 12; i++ { d := int(v.Value[i] - \u0026#39;0\u0026#39;) if i%2 == 0 { sum += d } else { sum += d * 3 } } expected := (10 - (sum % 10)) % 10 actual := int(v.Value[12] - \u0026#39;0\u0026#39;) if expected != actual { return fmt.Errorf(\u0026#34;invalid EAN-13 check digit: expected %d, got %d\u0026#34;, expected, actual) } return nil } MovementType as typed constants (not a struct):\n// internal/core/domain/movement_type.go type MovementType string const ( MovementTypeIn MovementType = \u0026#34;in\u0026#34; MovementTypeOut MovementType = \u0026#34;out\u0026#34; ) func NewMovementType(value string) (MovementType, error) { mt := MovementType(value) return mt, mt.Validate() } func (v MovementType) Validate() error { switch v { case MovementTypeIn, MovementTypeOut: return nil } return fmt.Errorf(\u0026#34;invalid movement type %q: must be %q or %q\u0026#34;, v, MovementTypeIn, MovementTypeOut) } Product entity with business methods // internal/core/domain/product.go func (e *Product) IsLowStock() bool { return e.CurrentStock \u0026lt;= e.MinStock } func (e *Product) Deactivate() { e.Active = false e.UpdatedAt = time.Now() } func (e *Product) ApplyMovement(movType MovementType, quantity float64) error { switch movType { case MovementTypeIn: e.CurrentStock += quantity case MovementTypeOut: if e.CurrentStock-quantity \u0026lt; 0 { return fmt.Errorf(\u0026#34;insufficient stock: available %.3f, requested %.3f\u0026#34;, e.CurrentStock, quantity) } e.CurrentStock -= quantity } e.UpdatedAt = time.Now() return nil } Ports (repository interfaces) // internal/core/domain/ports.go var ErrNotFound = errors.New(\u0026#34;not found\u0026#34;) type ProductRepository interface { Create(ctx context.Context, product *Product) error FindByEAN13(ctx context.Context, ean13 string) (*Product, error) Update(ctx context.Context, product *Product) error List(ctx context.Context, filter ProductFilter) ([]*Product, error) } type MovementRepository interface { Create(ctx context.Context, movement *Movement) error FindByID(ctx context.Context, id string) (*Movement, error) List(ctx context.Context, filter MovementFilter) ([]*Movement, error) // Atomic update: movement + stock in a single transaction CreateWithStockUpdate(ctx context.Context, movement *Movement, newStock float64) error } RecordMovement — The core service Implements the business rules: validate type, validate positive quantity, check sufficient stock, record the movement, and update stock atomically.\n// internal/core/services/record_movement.go func (s *RecordMovementService) Execute( ctx context.Context, input RecordMovementInput, ) (*RecordMovementOutput, error) { // Rule 1: valid movement type movType, err := domain.NewMovementType(input.Type) if err != nil { return nil, fmt.Errorf(\u0026#34;invalid movement type: %w\u0026#34;, err) } // Rule 2: quantity must be positive if _, err := domain.NewStockLevel(input.Quantity); err != nil { return nil, fmt.Errorf(\u0026#34;invalid quantity: %w\u0026#34;, err) } // Fetch product product, err := s.products.FindByEAN13(ctx, input.ProductEan13) if err != nil { return nil, fmt.Errorf(\u0026#34;product not found: %w\u0026#34;, err) } // Rule 3: check sufficient stock (for outbound movements) if err := product.ApplyMovement(movType, input.Quantity); err != nil { return nil, err } // Rule 4: UUID v4 generated in the service layer movement, err := domain.NewMovement(uuid.NewString(), input.ProductEan13, string(movType), input.Quantity, input.Reason, input.Notes, input.CreatedBy) if err != nil { return nil, err } // Rule 5: atomic database update if err := s.movements.CreateWithStockUpdate(ctx, movement, product.CurrentStock); err != nil { return nil, fmt.Errorf(\u0026#34;recording movement: %w\u0026#34;, err) } return \u0026amp;RecordMovementOutput{Movement: movement, Product: product}, nil } MovementRepository — Atomic transaction // internal/adapters/secondary/database/movement_repository.go func (r *MovementRepository) CreateWithStockUpdate( ctx context.Context, m *domain.Movement, newStock float64, ) error { tx, err := r.db.BeginTx(ctx, nil) if err != nil { return err } defer tx.Rollback() _, err = tx.ExecContext(ctx, `INSERT INTO movements (id, product_ean13, type, quantity, reason, notes, created_by, created_at) VALUES ($1,$2,$3,$4,$5,$6,$7,$8)`, m.Id, m.ProductEan13, m.Type, m.Quantity, m.Reason, m.Notes, m.CreatedBy, m.CreatedAt, ) if err != nil { return fmt.Errorf(\u0026#34;inserting movement: %w\u0026#34;, err) } _, err = tx.ExecContext(ctx, `UPDATE products SET current_stock=$1, updated_at=$2 WHERE ean13=$3`, newStock, time.Now(), m.ProductEan13, ) if err != nil { return fmt.Errorf(\u0026#34;updating product stock: %w\u0026#34;, err) } return tx.Commit() } ProductRepository — Dynamic filters // internal/adapters/secondary/database/product_repository.go func (r *ProductRepository) List( ctx context.Context, filter domain.ProductFilter, ) ([]*domain.Product, error) { q := `SELECT ean13, name, description, unit, min_stock, current_stock, category_id, active, created_at, updated_at FROM products WHERE 1=1` args := []any{} idx := 1 if filter.CategoryID != \u0026#34;\u0026#34; { q += fmt.Sprintf(\u0026#34; AND category_id = $%d\u0026#34;, idx) args = append(args, filter.CategoryID) idx++ } if filter.Active != nil { q += fmt.Sprintf(\u0026#34; AND active = $%d\u0026#34;, idx) args = append(args, *filter.Active) idx++ } if filter.LowStock { q += \u0026#34; AND current_stock \u0026lt;= min_stock\u0026#34; } q += \u0026#34; ORDER BY name\u0026#34; rows, err := r.db.QueryContext(ctx, q, args...) // ... scan rows } Shared HTTP Helpers // internal/adapters/primary/http/helpers.go package httpserver func respondJSON(w http.ResponseWriter, status int, data any) { w.Header().Set(\u0026#34;Content-Type\u0026#34;, \u0026#34;application/json\u0026#34;) w.WriteHeader(status) json.NewEncoder(w).Encode(data) } func respondHTTPError(w http.ResponseWriter, err error) { if errors.Is(err, domain.ErrNotFound) { respondError(w, http.StatusNotFound, err.Error()) return } respondError(w, http.StatusInternalServerError, \u0026#34;internal server error\u0026#34;) } Dependency injection in cmd/run.go // cmd/run.go — manual wiring, no DI framework db, err := sql.Open(\u0026#34;postgres\u0026#34;, cfg.Database.URL) // Secondary adapters productRepo := database.NewProductRepository(db) categoryRepo := database.NewCategoryRepository(db) movementRepo := database.NewMovementRepository(db) // Domain services manageProduct := services.NewManageProductService(productRepo) getProduct := services.NewGetProductService(productRepo) manageCategory := services.NewManageCategoryService(categoryRepo) recordMovement := services.NewRecordMovementService(productRepo, movementRepo) getMovements := services.NewGetMovementsService(movementRepo) getStockReport := services.NewGetStockReportService(productRepo) // Primary adapters productHandler := httpserver.NewProductHandler(manageProduct, getProduct, getMovements, getStockReport) categoryHandler := httpserver.NewCategoryHandler(manageCategory) movementHandler := httpserver.NewMovementHandler(recordMovement, getMovements) // HTTP Server srv := httpserver.New(\u0026amp;httpserver.ServerConfig{ Config: cfg, Logger: log, Metrics: metrics, Products: productHandler, Categories: categoryHandler, Movements: movementHandler, }) Bootstrapping Before trying to start the new app we must bootstrap it, meaning we need to create a database, a configuration file, and run the migrations to create the tables it will use.\nDatabase I already have Postgres and MariaDB instances running in my kubernetes cluster, so I just needed to create the database and an user to access it.\nCREATE DATABASE pantry; CREATE USER pantry WITH PASSWORD \u0026#39;secr3t\u0026#39;; GRANT ALL ON DATABASE pantry TO pantry_user; GRANT ALL ON SCHEMA public TO pantry_user; Configurarion file Created a .pantry.yaml file, as stated in the generated readme.md\nserver: port: 8080 host: 0.0.0.0 readtimeout: 15s writetimeout: 15s idletimeout: 60s shutdowntimeout: 30s database: url: postgres://pantry_user:secr3t@postgres.kube.patodiaz.dev:5432/pantry?sslmode=disable loglevel: info logformat: json Migration Now we should\u0026rsquo;ve run the migration from the app, but it was not possible as the coded was there but not connected to any way to trigger it, which led us to the session 3 with Claude.\nSession 3 — CLI command for migrations Claude knew how to implement the migration procedure but had no clue that it needed to be linked to a cli command from our app, or perhaps an API endpoint. So let\u0026rsquo;s ask Claude to expose it as a need command from or app.\n────────────────────────────────────────────────────────────────────────────────── ❯ create a command to run migrations? e.g.: pantry migrate ────────────────────────────────────────────────────────────────────────────────── Claude Code created cmd/migrate.go adding three subcommands to the CLI:\n// cmd/migrate.go var migrateCmd = \u0026amp;cobra.Command{ Use: \u0026#34;migrate\u0026#34;, Short: \u0026#34;Database migration management\u0026#34;, Long: `Run, rollback or inspect database migrations.`, } var migrateUpCmd = \u0026amp;cobra.Command{ Use: \u0026#34;up\u0026#34;, Short: \u0026#34;Apply all pending migrations\u0026#34;, RunE: func(cmd *cobra.Command, args []string) error { return withMigrator(func(m *infra.Migrator) error { return m.Up() }) }, } var migrateDownCmd = \u0026amp;cobra.Command{ Use: \u0026#34;down\u0026#34;, Short: \u0026#34;Roll back the last applied migration\u0026#34;, RunE: func(cmd *cobra.Command, args []string) error { return withMigrator(func(m *infra.Migrator) error { return m.Down() }) }, } var migrateVersionCmd = \u0026amp;cobra.Command{ Use: \u0026#34;version\u0026#34;, Short: \u0026#34;Show the current migration version\u0026#34;, RunE: func(cmd *cobra.Command, args []string) error { return withMigrator(func(m *infra.Migrator) error { version, dirty, err := m.Version() if err != nil { return err } dirtyFlag := \u0026#34;\u0026#34; if dirty { dirtyFlag = \u0026#34; (dirty)\u0026#34; } fmt.Printf(\u0026#34;Current migration version: %d%s\\n\u0026#34;, version, dirtyFlag) return nil }) }, } // withMigrator opens the DB, creates the Migrator, calls fn, then closes the DB. func withMigrator(fn func(*infra.Migrator) error) error { cfg := GetConfig() log := logger.New(\u0026amp;logger.Config{Level: cfg.LogLevel, Format: cfg.LogFormat}) db, err := sql.Open(\u0026#34;postgres\u0026#34;, cfg.Database.URL) if err != nil { return fmt.Errorf(\u0026#34;opening database: %w\u0026#34;, err) } defer db.Close() if err := db.Ping(); err != nil { return fmt.Errorf(\u0026#34;connecting to database: %w\u0026#34;, err) } return fn(infra.NewMigrator(db, log)) } func init() { migrateCmd.AddCommand(migrateUpCmd) migrateCmd.AddCommand(migrateDownCmd) migrateCmd.AddCommand(migrateVersionCmd) rootCmd.AddCommand(migrateCmd) } Usage:\n# Apply all pending migrations pantry migrate up # Roll back the last migration pantry migrate down # Show the current version pantry migrate version # Current migration version: 4 Back to finish the bootstrapping After resolving the missing migration command issue I just run the migration and created the tables. No issues.\n./pantry migrate up 2026/03/05 14:12:29 [INFO] Running migrations... 2026/03/05 14:12:30 [INFO] Migrations completed successfully $ psql pantry pantry_user psql (17.6) Type \u0026#34;help\u0026#34; for help. pantry=\u0026gt; \\dt List of relations Schema | Name | Type | Owner --------+-------------------+-------+------------- public | categories | table | pantry_user public | movements | table | pantry_user public | products | table | pantry_user public | schema_migrations | table | pantry_user (4 rows) pantry=\u0026gt; Tests I built and ran the app, then in another terminal:\n# add Grains \u0026amp; Pastas category $ curl -X POST --data \u0026#39;{\u0026#34;name\u0026#34;: \u0026#34;Grains \u0026amp; Pastas\u0026#34;}\u0026#39; http://localhost:8080/api/v1/categories {\u0026#34;id\u0026#34;:\u0026#34;30e3c996-48ca-452c-8c3a-22cd32db3e45\u0026#34;,\u0026#34;name\u0026#34;:\u0026#34;Grains \\u0026 Pastas\u0026#34;,\u0026#34;description\u0026#34;:\u0026#34;\u0026#34;,\u0026#34;created_at\u0026#34;:\u0026#34;2026-03-05T14:19:01.677334141-03:00\u0026#34;} # add Canned \u0026amp; Jarred Goods category $ curl -X POST --data \u0026#39;{\u0026#34;name\u0026#34;: \u0026#34;Canned \u0026amp; Jarred Goods\u0026#34;}\u0026#39; http://localhost:8080/api/v1/categories {\u0026#34;id\u0026#34;:\u0026#34;b4415623-ab49-4558-88e5-ae7604eef512\u0026#34;,\u0026#34;name\u0026#34;:\u0026#34;Canned \\u0026 Jarred Goods\u0026#34;,\u0026#34;description\u0026#34;:\u0026#34;\u0026#34;,\u0026#34;created_at\u0026#34;:\u0026#34;2026-03-05T14:19:32.83746188-03:00\u0026#34;} # list categories $ curl -s http://localhost:8080/api/v1/categories | jq [ { \u0026#34;id\u0026#34;: \u0026#34;b4415623-ab49-4558-88e5-ae7604eef512\u0026#34;, \u0026#34;name\u0026#34;: \u0026#34;Canned \u0026amp; Jarred Goods\u0026#34;, \u0026#34;description\u0026#34;: \u0026#34;\u0026#34;, \u0026#34;created_at\u0026#34;: \u0026#34;2026-03-05T14:19:32.837462Z\u0026#34; }, { \u0026#34;id\u0026#34;: \u0026#34;30e3c996-48ca-452c-8c3a-22cd32db3e45\u0026#34;, \u0026#34;name\u0026#34;: \u0026#34;Grains \u0026amp; Pastas\u0026#34;, \u0026#34;description\u0026#34;: \u0026#34;\u0026#34;, \u0026#34;created_at\u0026#34;: \u0026#34;2026-03-05T14:19:01.677334Z\u0026#34; } ] # register a product $ curl -X POST --data \u0026#39;{\u0026#34;name\u0026#34;: \u0026#34;Pasta Express\u0026#34;, \u0026#34;unit\u0026#34;: \u0026#34;gr\u0026#34;, \u0026#34;min_stock\u0026#34;: 2, \u0026#34;category_id\u0026#34;: \u0026#34;30e3c996-48ca-452c-8c3a-22cd32db3e45\u0026#34;}\u0026#39; http://localhost:8080/api/v1/products/0752356783662 | jq { \u0026#34;ean13\u0026#34;: \u0026#34;0752356783662\u0026#34;, \u0026#34;name\u0026#34;: \u0026#34;Pasta Express\u0026#34;, \u0026#34;description\u0026#34;: \u0026#34;\u0026#34;, \u0026#34;unit\u0026#34;: \u0026#34;gr\u0026#34;, \u0026#34;min_stock\u0026#34;: 2, \u0026#34;current_stock\u0026#34;: 0, \u0026#34;category_id\u0026#34;: \u0026#34;30e3c996-48ca-452c-8c3a-22cd32db3e45\u0026#34;, \u0026#34;active\u0026#34;: true, \u0026#34;created_at\u0026#34;: \u0026#34;2026-03-05T14:40:26.823634649-03:00\u0026#34;, \u0026#34;updated_at\u0026#34;: \u0026#34;2026-03-05T14:40:26.823634649-03:00\u0026#34; } # registrer a re-stocking $ curl -s -X POST --data \u0026#39;{\u0026#34;product_ean13\u0026#34;:\u0026#34;0752356783662\u0026#34;, \u0026#34;type\u0026#34;:\u0026#34;in\u0026#34;, \u0026#34;quantity\u0026#34;: 10, \u0026#34;reason\u0026#34;:\u0026#34;re-stocking\u0026#34;, \u0026#34;created_by\u0026#34;: \u0026#34;pato\u0026#34;}\u0026#39; http://localhost:8080/api/v1/movements | jq { \u0026#34;id\u0026#34;: \u0026#34;bc69126b-d306-4bff-ade6-87e54dc68a37\u0026#34;, \u0026#34;product_ean13\u0026#34;: \u0026#34;0752356783662\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;in\u0026#34;, \u0026#34;quantity\u0026#34;: 10, \u0026#34;reason\u0026#34;: \u0026#34;re-stocking\u0026#34;, \u0026#34;created_by\u0026#34;: \u0026#34;pato\u0026#34;, \u0026#34;created_at\u0026#34;: \u0026#34;2026-03-05T14:49:46.350019631-03:00\u0026#34; } # get product\u0026#39;s details $ curl -s http://localhost:8080/api/v1/products/0752356783662 | jq { \u0026#34;ean13\u0026#34;: \u0026#34;0752356783662\u0026#34;, \u0026#34;name\u0026#34;: \u0026#34;Pasta Express\u0026#34;, \u0026#34;description\u0026#34;: \u0026#34;\u0026#34;, \u0026#34;unit\u0026#34;: \u0026#34;gr\u0026#34;, \u0026#34;min_stock\u0026#34;: 2, \u0026#34;current_stock\u0026#34;: 10, \u0026#34;category_id\u0026#34;: \u0026#34;30e3c996-48ca-452c-8c3a-22cd32db3e45\u0026#34;, \u0026#34;active\u0026#34;: true, \u0026#34;created_at\u0026#34;: \u0026#34;2026-03-05T14:40:26.823635Z\u0026#34;, \u0026#34;updated_at\u0026#34;: \u0026#34;2026-03-05T14:49:46.367465Z\u0026#34; } # register a usage $ curl -s -X POST --data \u0026#39;{\u0026#34;product_ean13\u0026#34;:\u0026#34;0752356783662\u0026#34;, \u0026#34;type\u0026#34;:\u0026#34;out\u0026#34;, \u0026#34;quantity\u0026#34;: 1, \u0026#34;reason\u0026#34;:\u0026#34;Dinner\u0026#34;, \u0026#34;created_by\u0026#34;: \u0026#34;sonia\u0026#34;}\u0026#39; http://localhost:8080/api/v1/movements | jq { \u0026#34;id\u0026#34;: \u0026#34;490e73cc-5566-4ef6-a38c-f91994673a67\u0026#34;, \u0026#34;product_ean13\u0026#34;: \u0026#34;0752356783662\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;out\u0026#34;, \u0026#34;quantity\u0026#34;: 1, \u0026#34;reason\u0026#34;: \u0026#34;Dinner\u0026#34;, \u0026#34;created_by\u0026#34;: \u0026#34;sonia\u0026#34;, \u0026#34;created_at\u0026#34;: \u0026#34;2026-03-05T14:53:54.084178902-03:00\u0026#34; } # check current stock $ curl -s http://localhost:8080/api/v1/products/0752356783662/stock | jq { \u0026#34;current_stock\u0026#34;: 9, \u0026#34;ean13\u0026#34;: \u0026#34;0752356783662\u0026#34;, \u0026#34;is_low_stock\u0026#34;: false, \u0026#34;min_stock\u0026#34;: 2 } Errors encountered and how they were resolved 1. Package name conflict The scaffold generated handlers with package http, but server.go already used package httpserver. Solution: rewrite all files in the directory with package httpserver.\n// Before (conflicts with stdlib net/http) package http // After package httpserver 2. Scaffold tests with outdated API The scaffold generated tests referencing methods like service.Execute and types like services.ManageProductInput that had been replaced by specific methods (Create, Update, SetActive). Solution: replace the test files with stubs using t.Skip() until mocks are implemented.\nfunc TestManageProductService(t *testing.T) { t.Skip(\u0026#34;implement with mock repositories\u0026#34;) } 3. Dependencies not registered in go.mod When using github.com/google/uuid without having added it previously:\ngo get github.com/google/uuid github.com/stretchr/testify github.com/lib/pq go mod tidy 4. Compile-time interface check To ensure repositories correctly implement their interfaces:\n// At the top of each repository file var _ domain.ProductRepository = (*ProductRepository)(nil) If any method is missing, the compiler fails immediately with a clear error.\nResulting REST API GET /ping # health check # Categories GET /api/v1/categories # list all POST /api/v1/categories # create GET /api/v1/categories/{id} # get by ID PUT /api/v1/categories/{id} # update # Products GET /api/v1/products # list (?category=\u0026amp;active=\u0026amp;low_stock=) POST /api/v1/products/{ean13} # create GET /api/v1/products/{ean13} # get by EAN-13 PUT /api/v1/products/{ean13} # update DELETE /api/v1/products/{ean13} # deactivate (soft delete) GET /api/v1/products/{ean13}/stock # current stock GET /api/v1/products/{ean13}/movements # product movement history # Movements GET /api/v1/movements # history (?ean13=\u0026amp;type=\u0026amp;from=\u0026amp;to=) POST /api/v1/movements # record a movement GET /api/v1/movements/{id} # detail # Reports GET /api/v1/reports/stock # current stock summary GET /api/v1/reports/low-stock # products below minimum Final project structure pantry/ ├── cmd/ │ ├── root.go # Cobra root + Viper config │ ├── run.go # \u0026#34;run\u0026#34; command: DI wiring + start server │ └── migrate.go # \u0026#34;migrate\u0026#34; command: up/down/version ├── internal/ │ ├── config/ │ │ └── config.go # Config struct + load from env │ ├── core/ │ │ ├── domain/ │ │ │ ├── product.go │ │ │ ├── category.go │ │ │ ├── movement.go │ │ │ ├── e_a_n13.go # EAN-13 value object with GS1 validation │ │ │ ├── movement_type.go # Typed string constants │ │ │ ├── stock_level.go # Value object \u0026gt; 0 │ │ │ └── ports.go # Repository interfaces │ │ └── services/ │ │ ├── manage_product.go │ │ ├── get_product.go │ │ ├── manage_category.go │ │ ├── record_movement.go # \u0026lt;- Core service with business rules │ │ ├── get_movements.go │ │ └── get_stock_report.go │ ├── adapters/ │ │ ├── primary/http/ │ │ │ ├── server.go # Chi router + route setup │ │ │ ├── helpers.go # respondJSON, respondHTTPError, ... │ │ │ ├── product_handler.go │ │ │ ├── category_handler.go │ │ │ └── movement_handler.go │ │ └── secondary/database/ │ │ ├── product_repository.go │ │ ├── category_repository.go │ │ └── movement_repository.go # \u0026lt;- CreateWithStockUpdate (transaction) │ ├── infrastructure/ │ │ ├── database/ │ │ │ └── migrator.go # golang-migrate wrapper │ │ └── mapper/ │ │ ├── product_mapper.go │ │ └── movement_mapper.go │ └── observability/ │ ├── health.go │ ├── metrics.go │ └── server.go ├── migrations/ │ ├── 000001_create_categories_table.up.sql │ ├── 000001_create_categories_table.down.sql │ ├── 000002_create_products_table.up.sql │ ├── 000002_create_products_table.down.sql │ ├── 000003_create_movements_table.up.sql │ ├── 000003_create_movements_table.down.sql │ ├── 000004_add_stock_indexes.up.sql │ └── 000004_add_stock_indexes.down.sql ├── pkg/ │ ├── logger/ │ └── server/ ├── Dockerfile ├── compose.yaml ├── Makefile ├── go.mod └── main.go Conclusions What worked really well The natural-language prompt was enough: a single markdown file with the project spec was sufficient for Claude Code + Hexago to generate the entire structure without ambiguity.\nHexago MCP keeps the architecture honest: all 11 validations passed after scaffolding; the hexagonal dependency model was respected throughout the implementation.\nLayer-by-layer implementation: starting from the domain outward (value objects → entities → ports → services → repos → handlers → DI) avoided circular dependencies and made it easy to reason about each piece in isolation.\nBusiness rules explicit in code: ApplyMovement, IsLowStock, Deactivate live in the domain — not scattered between the handler and the repository.\nWhat required manual adjustment The scaffold generated some files with APIs that didn\u0026rsquo;t exactly match the chosen mplementation (generic Execute methods vs. semantically named methods). Resolved by replacing the stubs with correct implementations. The handler package needed renaming from http to httpserver to avoid the conflict with the standard library. Not an issue but something to improve in next versions. I changed the New procedure at internal\\adapters\\primary\\http\\server.go from: // server is the Chi-backed HTTP server. type server struct { router chi.Router httpSrv *http.Server cfg *config.Config log logger.Logger metrics *observability.PrometheusMetrics products *ProductHandler categories *CategoryHandler movements *MovementHandler } // New creates and configures a new Chi HTTP server with all handlers wired in. func New(cfg *config.Config, log logger.Logger, metrics *observability.PrometheusMetrics, productHandler *ProductHandler, categoryHandler *CategoryHandler, movementHandler *MovementHandler) srv.Server {... to\n// server is the Chi-backed HTTP server. type server struct { router chi.Router httpSrv *http.Server cfg *config.Config log logger.Logger metrics *observability.PrometheusMetrics products *ProductHandler categories *CategoryHandler movements *MovementHandler } type ServerConfig struct { Config *config.Config Logger logger.Logger Metrics *observability.PrometheusMetrics Products *ProductHandler Categories *CategoryHandler Movements *MovementHandler } // New creates and configures a new Chi HTTP server with all handlers wired in. func New(cfg *ServerConfig) srv.Server {... When implementing the Factory pattern it is a good practice to define a configuration struct type which will be the incomming parameter for the New function. This way the code is easier to read and also easier to implement unit-tests.\nNatural Next Steps These could be good subjects for next iterations with Claude Code\nUnit tests with mocks for the services. Integration tests for the repositories (using testcontainers-go). Implementation of ProductMapper and MovementMapper once persistence DTOs are defined. Final thoughts I\u0026rsquo;m quite happy with the outcome of this experiment, with just 3 iterations with Claude Code we ended up with a fully functional API. I\u0026rsquo;m aware that the result doesn\u0026rsquo;t implement any kind of security, but the structure is solid and adding it shouldn\u0026rsquo;t be a problem at all.\nBy the way, the project is here if anybody wants to check it.\n","permalink":"https://padiazg.github.io/posts/from-prompt-to-ready-api/","summary":"\u003cblockquote\u003e\n\u003cp\u003e\u003cstrong\u003eTL;DR\u003c/strong\u003e: In this session we gave Claude Code a descriptive natural-language prompt and,\nusing the \u003cstrong\u003eHexago\u003c/strong\u003e MCP server, it generated the complete scaffolding for a Go project\nwith hexagonal architecture. We then implemented all the business logic layer by layer\nuntil we had a working REST API with PostgreSQL, migrations, and a CLI command to manage them.\u003c/p\u003e\u003c/blockquote\u003e\n\u003chr\u003e\n\u003ch2 id=\"the-project-family-pantry-api\"\u003eThe project: Family Pantry API\u003c/h2\u003e\n\u003cp\u003eA backend API to manage a family pantry. Products are identified by their \u003cstrong\u003eEAN-13\u003c/strong\u003e barcode.\nThe system must:\u003c/p\u003e","title":"From prompt to ready API: Building a Go app with Claude Code and Hexago MCP"},{"content":"An unconventional approach to solving with Lambert\u0026rsquo;s W function\nBefore we move on to a practical real-world use case for an approximation root-finding algorithm, I want to share an anecdote from a time when, out of simple curiosity and a bit of boredom, I managed to solve an equation typically requiring the Lambert W function by approximating the root using the Newton-Raphson method.\n1. The video One day, a video on solving the equation \\(2^x + x = 5\\) popped up in my YouTube feed. The \\(x\\) in the exponent immediately piqued my curiosity. After watching the entire video, I was introduced to the Lambert W function—\u0026ldquo;Nice to meet you,\u0026rdquo; I thought. For a moment, I debated whether I should dive deeper into learning about it, or consider how I might use it in the future. Then, I took another look at the equation and noticed it was a differentiable function. That\u0026rsquo;s when it hit me: I should tackle the problem using one of the root-finding algorithms.\n2. Hands on Let\u0026rsquo;s methodologically assemble the iterative equation and see if we can converge into a root. From here, the Newton-Raphson iterative formula is applied:\n$$ \\begin{align} 2^x+x \u0026= 5 \u0026\\text{this is the equation we want to solve} \\\\ 2^x+x -5 \u0026= 0 \u0026\\text{rearrange to express it in standard form}\\\\ f(x) \u0026= 2^{x} + x - 5 \u0026\\text{define f(x) as the fucntion whose root we seek}\\\\ f'(x) \u0026= 2^{x} \\cdot log(2) + 1 \u0026\\text{the derivative} \\\\ f'(x) \u0026= 0,3010299957 \\cdot 2^{x} + 1 \u0026 \\text{we can use log(2) as a constant from here} \\\\ \\\\ x_{n+1} \u0026= x_{n}-\\frac{f(x_{n})}{f'(x_{n})} \\\\ \\\\ x_{n+1} \u0026= x_{n}-\\frac{2^{x_{n}} + x_{n} - 5}{0,3010299957 \\cdot 2^{x_{n}} + 1} \u0026 \\text{the ecuation we will iterate} \\\\ \\\\ precicion \u0026= 0,0000001 \\\\ \\end{align} $$ With a precision threshold of 7, the iterations proceed as follows: $$ \\begin{align} x_{0} \u0026= 1 \u0026 \\text{initial guess} \\\\ x_{1} \u0026= x_{0}-\\frac{2^{x_{0}} + x_{0} - 5}{log(2) \\cdot 2^{x_{0}} + 1}\u0026=1,0 - \\frac{2^{1,0} + 1,0- 5}{0,3010299957 \\cdot 2^{1,0} + 1}\u0026={\\color{gray}2,248392701} \u0026|x_{1}-x_{0}| \u0026=1,2483927 \\\\ x_{2} \u0026= x_{1}-\\frac{2^{x_{1}} + x_{1} - 5}{log(2) \\cdot 2^{x_{1}} + 1}\u0026=2,2483927 - \\frac{2^{2,2483927} + 2,2483927- 5}{0,3010299957 \\cdot 2^{2,2483927} + 1}\u0026={\\color{red}\\underline{1,}}{\\color{gray}425498229} \u0026|x_{2}-x_{1}| \u0026=0,82289447 \\\\ x_{3} \u0026= x_{2}-\\frac{2^{x_{2}} + x_{2} - 5}{log(2) \\cdot 2^{x_{2}} + 1}\u0026=1,42549823 - \\frac{2^{1,42549823} + 1,42549823- 5}{0,3010299957 \\cdot 2^{1,42549823} + 1}\u0026={\\color{red}\\underline{1,}}{\\color{gray}916726255} \u0026|x_{3}-x_{2}| \u0026=0,49122803 \\\\ x_{4} \u0026= x_{3}-\\frac{2^{x_{3}} + x_{3} - 5}{log(2) \\cdot 2^{x_{3}} + 1}\u0026=1,91672625 - \\frac{2^{1,91672625} + 1,91672625- 5}{0,3010299957 \\cdot 2^{1,91672625} + 1}\u0026={\\color{red}\\underline{1,}}{\\color{gray}592667304} \u0026|x_{4}-x_{3}| \u0026=0,32405895 \\\\ x_{5} \u0026= x_{4}-\\frac{2^{x_{4}} + x_{4} - 5}{log(2) \\cdot 2^{x_{4}} + 1}\u0026=1,5926673 - \\frac{2^{1,5926673} + 1,5926673- 5}{0,3010299957 \\cdot 2^{1,5926673} + 1}\u0026={\\color{red}\\underline{1,}}{\\color{gray}797742433} \u0026|x_{5}-x_{4}| \u0026=0,20507513 \\\\ x_{6} \u0026= x_{5}-\\frac{2^{x_{5}} + x_{5} - 5}{log(2) \\cdot 2^{x_{5}} + 1}\u0026=1,79774243 - \\frac{2^{1,79774243} + 1,79774243- 5}{0,3010299957 \\cdot 2^{1,79774243} + 1}\u0026={\\color{red}\\underline{1,}}{\\color{gray}663618132} \u0026|x_{6}-x_{5}| \u0026=0,1341243 \\\\ x_{7} \u0026= x_{6}-\\frac{2^{x_{6}} + x_{6} - 5}{log(2) \\cdot 2^{x_{6}} + 1}\u0026=1,66361813 - \\frac{2^{1,66361813} + 1,66361813- 5}{0,3010299957 \\cdot 2^{1,66361813} + 1}\u0026={\\color{red}\\underline{1,7}}{\\color{gray}49753096} \u0026|x_{7}-x_{6}| \u0026=0,08613496 \\\\ x_{8} \u0026= x_{7}-\\frac{2^{x_{7}} + x_{7} - 5}{log(2) \\cdot 2^{x_{7}} + 1}\u0026=1,7497531 - \\frac{2^{1,7497531} + 1,7497531- 5}{0,3010299957 \\cdot 2^{1,7497531} + 1}\u0026={\\color{red}\\underline{1,6}}{\\color{gray}93718007} \u0026|x_{8}-x_{7}| \u0026=0,05603509 \\\\ x_{9} \u0026= x_{8}-\\frac{2^{x_{8}} + x_{8} - 5}{log(2) \\cdot 2^{x_{8}} + 1}\u0026=1,69371801 - \\frac{2^{1,69371801} + 1,69371801- 5}{0,3010299957 \\cdot 2^{1,69371801} + 1}\u0026={\\color{red}\\underline{1,7}}{\\color{gray}29886296} \u0026|x_{9}-x_{8}| \u0026=0,03616829 \\\\ x_{10} \u0026= x_{9}-\\frac{2^{x_{9}} + x_{9} - 5}{log(2) \\cdot 2^{x_{9}} + 1}\u0026=1,7298863 - \\frac{2^{1,7298863} + 1,7298863- 5}{0,3010299957 \\cdot 2^{1,7298863} + 1}\u0026={\\color{red}\\underline{1,7}}{\\color{gray}06417426} \u0026|x_{10}-x_{9}| \u0026=0,02346887 \\\\ x_{11} \u0026= x_{10}-\\frac{2^{x_{10}} + x_{10} - 5}{log(2) \\cdot 2^{x_{10}} + 1}\u0026=1,70641743 - \\frac{2^{1,70641743} + 1,70641743- 5}{0,3010299957 \\cdot 2^{1,70641743} + 1}\u0026={\\color{red}\\underline{1,7}}{\\color{gray}21595160} \u0026|x_{11}-x_{10}| \u0026=0,01517773 \\\\ x_{12} \u0026= x_{11}-\\frac{2^{x_{11}} + x_{11} - 5}{log(2) \\cdot 2^{x_{11}} + 1}\u0026=1,72159516 - \\frac{2^{1,72159516} + 1,72159516- 5}{0,3010299957 \\cdot 2^{1,72159516} + 1}\u0026={\\color{red}\\underline{1,71}}{\\color{gray}1757864} \u0026|x_{12}-x_{11}| \u0026=0,0098373 \\\\ x_{13} \u0026= x_{12}-\\frac{2^{x_{12}} + x_{12} - 5}{log(2) \\cdot 2^{x_{12}} + 1}\u0026=1,71175786 - \\frac{2^{1,71175786} + 1,71175786- 5}{0,3010299957 \\cdot 2^{1,71175786} + 1}\u0026={\\color{red}\\underline{1,71}}{\\color{gray}8124841} \u0026|x_{13}-x_{12}| \u0026=0,00636698 \\\\ x_{14} \u0026= x_{13}-\\frac{2^{x_{13}} + x_{13} - 5}{log(2) \\cdot 2^{x_{13}} + 1}\u0026=1,71812484 - \\frac{2^{1,71812484} + 1,71812484- 5}{0,3010299957 \\cdot 2^{1,71812484} + 1}\u0026={\\color{red}\\underline{1,71}}{\\color{gray}4000170} \u0026|x_{14}-x_{13}| \u0026=0,00412467 \\\\ x_{15} \u0026= x_{14}-\\frac{2^{x_{14}} + x_{14} - 5}{log(2) \\cdot 2^{x_{14}} + 1}\u0026=1,71400017 - \\frac{2^{1,71400017} + 1,71400017- 5}{0,3010299957 \\cdot 2^{1,71400017} + 1}\u0026={\\color{red}\\underline{1,71}}{\\color{gray}6670644} \u0026|x_{15}-x_{14}| \u0026=0,00267047 \\\\ x_{16} \u0026= x_{15}-\\frac{2^{x_{15}} + x_{15} - 5}{log(2) \\cdot 2^{x_{15}} + 1}\u0026=1,71667064 - \\frac{2^{1,71667064} + 1,71667064- 5}{0,3010299957 \\cdot 2^{1,71667064} + 1}\u0026={\\color{red}\\underline{1,71}}{\\color{gray}4941009} \u0026|x_{16}-x_{15}| \u0026=0,00172964 \\\\ x_{17} \u0026= x_{16}-\\frac{2^{x_{16}} + x_{16} - 5}{log(2) \\cdot 2^{x_{16}} + 1}\u0026=1,71494101 - \\frac{2^{1,71494101} + 1,71494101- 5}{0,3010299957 \\cdot 2^{1,71494101} + 1}\u0026={\\color{red}\\underline{1,71}}{\\color{gray}6060995} \u0026|x_{17}-x_{16}| \u0026=0,00111999 \\\\ x_{18} \u0026= x_{17}-\\frac{2^{x_{17}} + x_{17} - 5}{log(2) \\cdot 2^{x_{17}} + 1}\u0026=1,716061 - \\frac{2^{1,716061} + 1,716061- 5}{0,3010299957 \\cdot 2^{1,716061} + 1}\u0026={\\color{red}\\underline{1,715}}{\\color{gray}335657} \u0026|x_{18}-x_{17}| \u0026=0,00072534 \\\\ x_{19} \u0026= x_{18}-\\frac{2^{x_{18}} + x_{18} - 5}{log(2) \\cdot 2^{x_{18}} + 1}\u0026=1,71533566 - \\frac{2^{1,71533566} + 1,71533566- 5}{0,3010299957 \\cdot 2^{1,71533566} + 1}\u0026={\\color{red}\\underline{1,715}}{\\color{gray}805360} \u0026|x_{19}-x_{18}| \u0026=0,0004697 \\\\ x_{20} \u0026= x_{19}-\\frac{2^{x_{19}} + x_{19} - 5}{log(2) \\cdot 2^{x_{19}} + 1}\u0026=1,71580536 - \\frac{2^{1,71580536} + 1,71580536- 5}{0,3010299957 \\cdot 2^{1,71580536} + 1}\u0026={\\color{red}\\underline{1,715}}{\\color{gray}501177} \u0026|x_{20}-x_{19}| \u0026=0,00030418 \\\\ x_{21} \u0026= x_{20}-\\frac{2^{x_{20}} + x_{20} - 5}{log(2) \\cdot 2^{x_{20}} + 1}\u0026=1,71550118 - \\frac{2^{1,71550118} + 1,71550118- 5}{0,3010299957 \\cdot 2^{1,71550118} + 1}\u0026={\\color{red}\\underline{1,715}}{\\color{gray}698160} \u0026|x_{21}-x_{20}| \u0026=0,00019698 \\\\ x_{22} \u0026= x_{21}-\\frac{2^{x_{21}} + x_{21} - 5}{log(2) \\cdot 2^{x_{21}} + 1}\u0026=1,71569816 - \\frac{2^{1,71569816} + 1,71569816- 5}{0,3010299957 \\cdot 2^{1,71569816} + 1}\u0026={\\color{red}\\underline{1,715}}{\\color{gray}570594} \u0026|x_{22}-x_{21}| \u0026=0,00012757 \\\\ x_{23} \u0026= x_{22}-\\frac{2^{x_{22}} + x_{22} - 5}{log(2) \\cdot 2^{x_{22}} + 1}\u0026=1,71557059 - \\frac{2^{1,71557059} + 1,71557059- 5}{0,3010299957 \\cdot 2^{1,71557059} + 1}\u0026={\\color{red}\\underline{1,7156}}{\\color{gray}53204} \u0026|x_{23}-x_{22}| \u0026=0,00008261 \\\\ x_{24} \u0026= x_{23}-\\frac{2^{x_{23}} + x_{23} - 5}{log(2) \\cdot 2^{x_{23}} + 1}\u0026=1,7156532 - \\frac{2^{1,7156532} + 1,7156532- 5}{0,3010299957 \\cdot 2^{1,7156532} + 1}\u0026={\\color{red}\\underline{1,7155}}{\\color{gray}99706} \u0026|x_{24}-x_{23}| \u0026=0,0000535 \\\\ x_{25} \u0026= x_{24}-\\frac{2^{x_{24}} + x_{24} - 5}{log(2) \\cdot 2^{x_{24}} + 1}\u0026=1,71559971 - \\frac{2^{1,71559971} + 1,71559971- 5}{0,3010299957 \\cdot 2^{1,71559971} + 1}\u0026={\\color{red}\\underline{1,7156}}{\\color{gray}34350} \u0026|x_{25}-x_{24}| \u0026=0,00003464 \\\\ x_{26} \u0026= x_{25}-\\frac{2^{x_{25}} + x_{25} - 5}{log(2) \\cdot 2^{x_{25}} + 1}\u0026=1,71563435 - \\frac{2^{1,71563435} + 1,71563435- 5}{0,3010299957 \\cdot 2^{1,71563435} + 1}\u0026={\\color{red}\\underline{1,7156}}{\\color{gray}11915} \u0026|x_{26}-x_{25}| \u0026=0,00002244 \\\\ x_{27} \u0026= x_{26}-\\frac{2^{x_{26}} + x_{26} - 5}{log(2) \\cdot 2^{x_{26}} + 1}\u0026=1,71561191 - \\frac{2^{1,71561191} + 1,71561191- 5}{0,3010299957 \\cdot 2^{1,71561191} + 1}\u0026={\\color{red}\\underline{1,7156}}{\\color{gray}26444} \u0026|x_{27}-x_{26}| \u0026=0,00001453 \\\\ x_{28} \u0026= x_{27}-\\frac{2^{x_{27}} + x_{27} - 5}{log(2) \\cdot 2^{x_{27}} + 1}\u0026=1,71562644 - \\frac{2^{1,71562644} + 1,71562644- 5}{0,3010299957 \\cdot 2^{1,71562644} + 1}\u0026={\\color{red}\\underline{1,71561}}{\\color{gray}7035} \u0026|x_{28}-x_{27}| \u0026=0,00000941 \\\\ x_{29} \u0026= x_{28}-\\frac{2^{x_{28}} + x_{28} - 5}{log(2) \\cdot 2^{x_{28}} + 1}\u0026=1,71561704 - \\frac{2^{1,71561704} + 1,71561704- 5}{0,3010299957 \\cdot 2^{1,71561704} + 1}\u0026={\\color{red}\\underline{1,71562}}{\\color{gray}3128} \u0026|x_{29}-x_{28}| \u0026=0,00000609 \\\\ x_{30} \u0026= x_{29}-\\frac{2^{x_{29}} + x_{29} - 5}{log(2) \\cdot 2^{x_{29}} + 1}\u0026=1,71562313 - \\frac{2^{1,71562313} + 1,71562313- 5}{0,3010299957 \\cdot 2^{1,71562313} + 1}\u0026={\\color{red}\\underline{1,71561}}{\\color{gray}9182} \u0026|x_{30}-x_{29}| \u0026=0,00000395 \\\\ x_{31} \u0026= x_{30}-\\frac{2^{x_{30}} + x_{30} - 5}{log(2) \\cdot 2^{x_{30}} + 1}\u0026=1,71561918 - \\frac{2^{1,71561918} + 1,71561918- 5}{0,3010299957 \\cdot 2^{1,71561918} + 1}\u0026={\\color{red}\\underline{1,71562}}{\\color{gray}1738} \u0026|x_{31}-x_{30}| \u0026=0,00000256 \\\\ x_{32} \u0026= x_{31}-\\frac{2^{x_{31}} + x_{31} - 5}{log(2) \\cdot 2^{x_{31}} + 1}\u0026=1,71562174 - \\frac{2^{1,71562174} + 1,71562174- 5}{0,3010299957 \\cdot 2^{1,71562174} + 1}\u0026={\\color{red}\\underline{1,71562}}{\\color{gray}0083} \u0026|x_{32}-x_{31}| \u0026=0,00000165 \\\\ x_{33} \u0026= x_{32}-\\frac{2^{x_{32}} + x_{32} - 5}{log(2) \\cdot 2^{x_{32}} + 1}\u0026=1,71562008 - \\frac{2^{1,71562008} + 1,71562008- 5}{0,3010299957 \\cdot 2^{1,71562008} + 1}\u0026={\\color{red}\\underline{1,71562}}{\\color{gray}1154} \u0026|x_{33}-x_{32}| \u0026=0,00000107 \\\\ x_{34} \u0026= x_{33}-\\frac{2^{x_{33}} + x_{33} - 5}{log(2) \\cdot 2^{x_{33}} + 1}\u0026=1,71562115 - \\frac{2^{1,71562115} + 1,71562115- 5}{0,3010299957 \\cdot 2^{1,71562115} + 1}\u0026={\\color{red}\\underline{1,715620}}{\\color{gray}461} \u0026|x_{34}-x_{33}| \u0026=0,00000069 \\\\ x_{35} \u0026= x_{34}-\\frac{2^{x_{34}} + x_{34} - 5}{log(2) \\cdot 2^{x_{34}} + 1}\u0026=1,71562046 - \\frac{2^{1,71562046} + 1,71562046- 5}{0,3010299957 \\cdot 2^{1,71562046} + 1}\u0026={\\color{red}\\underline{1,715620}}{\\color{gray}910} \u0026|x_{35}-x_{34}| \u0026=0,00000045 \\\\ x_{36} \u0026= x_{35}-\\frac{2^{x_{35}} + x_{35} - 5}{log(2) \\cdot 2^{x_{35}} + 1}\u0026=1,71562091 - \\frac{2^{1,71562091} + 1,71562091- 5}{0,3010299957 \\cdot 2^{1,71562091} + 1}\u0026={\\color{red}\\underline{1,715620}}{\\color{gray}619} \u0026|x_{36}-x_{35}| \u0026=0,00000029 \\\\ x_{37} \u0026= x_{36}-\\frac{2^{x_{36}} + x_{36} - 5}{log(2) \\cdot 2^{x_{36}} + 1}\u0026=1,71562062 - \\frac{2^{1,71562062} + 1,71562062- 5}{0,3010299957 \\cdot 2^{1,71562062} + 1}\u0026={\\color{red}\\underline{1,715620}}{\\color{gray}807} \u0026|x_{37}-x_{36}| \u0026=0,00000019 \\\\ x_{38} \u0026= x_{37}-\\frac{2^{x_{37}} + x_{37} - 5}{log(2) \\cdot 2^{x_{37}} + 1}\u0026=1,71562081 - \\frac{2^{1,71562081} + 1,71562081- 5}{0,3010299957 \\cdot 2^{1,71562081} + 1}\u0026={\\color{red}\\underline{1,715620}}{\\color{gray}685} \u0026|x_{38}-x_{37}| \u0026=0,00000012 \\\\ x_{39} \u0026= x_{38}-\\frac{2^{x_{38}} + x_{38} - 5}{log(2) \\cdot 2^{x_{38}} + 1}\u0026=1,71562069 - \\frac{2^{1,71562069} + 1,71562069- 5}{0,3010299957 \\cdot 2^{1,71562069} + 1}\u0026={\\color{red}\\underline{1,7156207}}{\\color{gray}64} \u0026|x_{39}-x_{38}| \u0026=0,00000008 \\\\ \\end{align} $$ It took 39 iterations to achieve 7-decimal precision for the root. While this number seems high, the convergence was steady, with significant progress in the first 10 iterations.\n3. Wrapping up Using a root-finding algorithm like Newton-Raphson to solve instead of the Lambert W function offers several advantages in implementation simplicity. The Lambert W function is mathematically elegant but less commonly supported in programming libraries, making its direct application a challenge in some environments. On the other hand, root-finding algorithms require only basic mathematical tools available in almost every computational framework.\nDespite requiring 39 iterations to achieve a solution with 7-decimal precision, the iterative process was straightforward. It followed a mechanical pattern: evaluate the function, compute the derivative, and update the guess. In cases where computational time is not critical—like this mathematical exploration—such methods provide a robust alternative that leverages fundamental calculus.\nThis journey underscores the versatility of mathematical problem-solving. By revisiting a problem with a fresh perspective, we see how classical techniques can rival or complement specialized tools. Whether for academic curiosity or practical applications, understanding these foundational approaches broadens our computational toolkit.\nLinks Numerical root-finding algorithms: Foundations, theory, and advanced methods. Part 1 Numerical root-finding algorithms: Bisection, Newton-Raphson and Secant. Part2 Numerical root-finding algorithms: An unconventional approach. Part3 ","permalink":"https://padiazg.github.io/posts/numerical-root-finding-part3/","summary":"\u003cp\u003e\u003cstrong\u003eAn unconventional approach to solving with Lambert\u0026rsquo;s W function\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eBefore we move on to a practical real-world use case for an approximation root-finding algorithm, I want to share an anecdote from a time when, out of simple curiosity and a bit of boredom, I managed to solve an equation typically requiring the Lambert W function by approximating the root using the Newton-Raphson method.\u003c/p\u003e\n\u003ch2 id=\"1-the-video\"\u003e1. The video\u003c/h2\u003e\n\u003cp\u003eOne day, a \u003ca href=\"https://www.youtube.com/watch?v=mJwfpcXwYRU\"\u003evideo\u003c/a\u003e on solving the equation \\(2^x + x = 5\\) popped up in my YouTube feed. The \\(x\\) in the exponent immediately piqued my curiosity. After watching the entire video, I was introduced to the Lambert W function—\u0026ldquo;Nice to meet you,\u0026rdquo; I thought. For a moment, I debated whether I should dive deeper into learning about it, or consider how I might use it in the future. Then, I took another look at the equation and noticed it was a differentiable function. That\u0026rsquo;s when it hit me: I should tackle the problem using one of the root-finding algorithms.\u003c/p\u003e","title":"Numerical root-finding algorithms: An unconventional approach. Part 3"},{"content":"Continuing our series on root-finding algorithms, this article delves deeper into the Bisection (linear convergence), Newton-Raphson (quadratic convergence), and Secant (super linear convergence) methods. Each of these algorithms has unique strengths, making them suitable for different scenarios. To illustrate their application, we will use the example of calculating the square root of a number—a simple yet insightful problem.\nUsing an approximation algorithm to calculate a square root might seem excessive, but please bear with me throughout this article. I chose the square root because the function is straightforward, and its derivative is relatively simple to calculate, allowing us to work through the exercises more easily.\n$$ \\begin{align} x\u0026=\\sqrt{m} \u0026\\text{define x as the square root of m} \\\\ x^2\u0026=m \u0026\\text{squaring both sides to remove the square root} \\\\ x^2-m\u0026=0 \u0026\\text{rearrange to express the equation in standard form} \\\\ f(x)\u0026=x^2-m \u0026\\text{define f(x) as the function whose root we seek} \\\\ \\end{align} $$Check the Code Examples at the end of the article for the link to the repo with the code. 1. Bisection The bisection algorithm is a simple and reliable numerical method for finding roots of continuous functions. It is particularly well-suited for situations where the function is continuous and the root lies within a known interval. Unlike some other methods, the bisection algorithm guarantees convergence to a root, provided the conditions are met, making it a popular choice for solving equations of the form \\(f(x) = 0\\).\nHow It Works: The method starts with an interval \\([a,b]\\) where the function \\(f(x)\\) changes sign. This means \\(f(a) \\cdot f(b) \u003c 0\\), indicating that a root lies somewhere in the interval (due to the Intermediate Value Theorem). The algorithm then repeatedly bisects the interval, narrowing it down until the root is approximated to a desired level of accuracy.\nThe steps are:\nCompute the midpoint of the interval: $$ r = \\frac{a + b}{2} $$ Evaluate \\(f(r)\\):\nIf \\(f(r) = 0\\), \\(c\\) is the exact root, and the algorithm stops. If \\(f(a) \\cdot f(r) \u003c 0\\), the root lies in the subinterval \\([a,r]\\), so \\(b\\) is updated to \\(r\\). Otherwise, the root lies in the subinterval \\([r, b]\\), so \\(a\\) is updated to \\(r\\) Repeat this process until the interval is sufficiently small, such that \\(∣b−a∣\\) is within a predefined tolerance.\nUse case: Square root For \\(m=2\\) Means we want to get the result for this equation: \\(x=\\sqrt{m}\\).\nLet´s take \\([a.b]=[0,2]\\) as the values bracket. We know the square root of a number \\(m\\) satisfies \\(0 \\leq \\sqrt{m} \\leq m\\) only if \\(m \\geq 1\\), for \\(0 \\leq m \u003c 1\\), \\(\\sqrt{m} \\geq m\\). So, it\u0026rsquo;s safe to use this numbers for this exercise.\nOn each iteration we will evaluate only \\(f_{n}(a) \\cdot f_{n}(r)\\) as they are exclusive with \\(f_{n}(b) \\cdot f_{n}(r)\\). if one is positive the other is negative. If \\(f(r)=0\\) then we stop. If we don\u0026rsquo;t need an exact result and we are happy with certain amount of precision we ca use the error to check if we achieved the precision we need. ex: if we need 4 digits precision we can check for \\(err \\leq 0.00001\\), which the example below this is satisfied at \\(r_{18}\\). $$ \\begin{align} m \u0026= 2 \\\\ [a.b] \u0026= [0,2] \\\\ r_{0} \u0026= \\frac{0 + 2}{2} = 1 \u0026 \\text{initial result}\\\\ \\\\ x \u0026= r_{n} \u0026 \\text{if } f_{n}(r)=0 \\text{, stop iterating} \\\\ \\\\ v_{n+1} \u0026= f_{n}(a) \\cdot f_{n}(r) \u0026 \\text{evaluate} \\\\ \\\\ a_{n+1} \u0026= \\begin{cases} a_{n} \u0026 \\text{if } v_{n+1} \u003c 0 \\\\ r_{n} \u0026 \\text{otherwise} \\end{cases} \\\\ \\\\ b_{n+1} \u0026= \\begin{cases} r_{n} \u0026 \\text{if } v_{n+1} \u003c 0 \\\\ b_{n} \u0026 \\text{otherwise} \\end{cases} \\\\ \\\\ e_{n} \u0026= b_{n}-a_{n} \u0026 \\text{error} \\\\ \\end{align} $$ $$ \\begin{align*} a_{1}\u0026=1,0 \u0026r_{1}\u0026=1,5 \u0026b_{1}\u0026=2,0 \u0026f_{1}(a)\u0026=-1,0 \u0026f_{1}(r)\u0026=2,0 \u0026f_{1}(b)\u0026=0,25 \u0026v_{1}\u0026=-0,25 \u0026v_{0} \u003e 0 \u0026\\dots r_{0} \\to a_{1} \u0026e\u0026=1,0 \\\\ a_{2}\u0026=1,0 \u0026r_{2}\u0026=1,25 \u0026b_{2}\u0026=1,5 \u0026f_{2}(a)\u0026=-1,0 \u0026f_{2}(r)\u0026=0,25 \u0026f_{2}(b)\u0026=-0,4375 \u0026v_{2}\u0026=0,4375 \u0026v_{1} \u003c 0 \u0026\\dots r_{1} \\to b_{2} \u0026e\u0026=0,5 \\\\ a_{3}\u0026=1,25 \u0026r_{3}\u0026=1,375 \u0026b_{3}\u0026=1,5 \u0026f_{3}(a)\u0026=-0,4375 \u0026f_{3}(r)\u0026=0,25 \u0026f_{3}(b)\u0026=-0,109375 \u0026v_{3}\u0026=0,0478515625 \u0026v_{2} \u003e 0 \u0026\\dots r_{2} \\to a_{3} \u0026e\u0026=0,25 \\\\ a_{4}\u0026=1,375 \u0026r_{4}\u0026=1,4375 \u0026b_{4}\u0026=1,5 \u0026f_{4}(a)\u0026=-0,109375 \u0026f_{4}(r)\u0026=0,25 \u0026f_{4}(b)\u0026=0,06640625 \u0026v_{4}\u0026=-0,00726318359375 \u0026v_{3} \u003e 0 \u0026\\dots r_{3} \\to a_{4} \u0026e\u0026=0,125 \\\\ a_{5}\u0026=1,375 \u0026r_{5}\u0026=1,40625 \u0026b_{5}\u0026=1,4375 \u0026f_{5}(a)\u0026=-0,109375 \u0026f_{5}(r)\u0026=0,06640625 \u0026f_{5}(b)\u0026=-0,02246094 \u0026v_{5}\u0026=0,0024566650390625 \u0026v_{4} \u003c 0 \u0026\\dots r_{4} \\to b_{5} \u0026e\u0026=0,0625 \\\\ a_{6}\u0026=1,40625 \u0026r_{6}\u0026=1,421875 \u0026b_{6}\u0026=1,4375 \u0026f_{6}(a)\u0026=-0,02246094 \u0026f_{6}(r)\u0026=0,06640625 \u0026f_{6}(b)\u0026=0,02172852 \u0026v_{6}\u0026=-0,0004880428314209 \u0026v_{5} \u003e 0 \u0026\\dots r_{5} \\to a_{6} \u0026e\u0026=0,03125 \\\\ a_{7}\u0026=1,40625 \u0026r_{7}\u0026=1,4140625 \u0026b_{7}\u0026=1,421875 \u0026f_{7}(a)\u0026=-0,02246094 \u0026f_{7}(r)\u0026=0,02172852 \u0026f_{7}(b)\u0026=-0,00042725 \u0026v_{7}\u0026=0,00000959634780884 \u0026v_{6} \u003c 0 \u0026\\dots r_{6} \\to b_{7} \u0026e\u0026=0,015625 \\\\ a_{8}\u0026=1,4140625 \u0026r_{8}\u0026=1,41796875 \u0026b_{8}\u0026=1,421875 \u0026f_{8}(a)\u0026=-0,00042725 \u0026f_{8}(r)\u0026=0,02172852 \u0026f_{8}(b)\u0026=0,01063538 \u0026v_{8}\u0026=-0,00000454392284155 \u0026v_{7} \u003e 0 \u0026\\dots r_{7} \\to a_{8} \u0026e\u0026=0,0078125 \\\\ a_{9}\u0026=1,4140625 \u0026r_{9}\u0026=1,41601563 \u0026b_{9}\u0026=1,41796875 \u0026f_{9}(a)\u0026=-0,00042725 \u0026f_{9}(r)\u0026=0,01063538 \u0026f_{9}(b)\u0026=0,00510025 \u0026v_{9}\u0026=-0,00000217906199396 \u0026v_{8} \u003c 0 \u0026\\dots r_{8} \\to b_{9} \u0026e\u0026=0,00390625 \\\\ a_{10}\u0026=1,4140625 \u0026r_{10}\u0026=1,41503906 \u0026b_{10}\u0026=1,41601563 \u0026f_{10}(a)\u0026=-0,00042725 \u0026f_{10}(r)\u0026=0,00510025 \u0026f_{10}(b)\u0026=0,00233555 \u0026v_{10}\u0026=-0,00000099785393104 \u0026v_{9} \u003c 0 \u0026\\dots r_{9} \\to b_{10} \u0026e\u0026=0,00195313 \\\\ a_{11}\u0026=1,4140625 \u0026r_{11}\u0026=1,41455078 \u0026b_{11}\u0026=1,41503906 \u0026f_{11}(a)\u0026=-0,00042725 \u0026f_{11}(r)\u0026=0,00233555 \u0026f_{11}(b)\u0026=0,00095391 \u0026v_{11}\u0026=-0,0000004075554898 \u0026v_{10} \u003c 0 \u0026\\dots r_{10} \\to b_{11} \u0026e\u0026=0,00097656 \\\\ a_{12}\u0026=1,4140625 \u0026r_{12}\u0026=1,41430664 \u0026b_{12}\u0026=1,41455078 \u0026f_{12}(a)\u0026=-0,00042725 \u0026f_{12}(r)\u0026=0,00095391 \u0026f_{12}(b)\u0026=0,00026327 \u0026v_{12}\u0026=-0,00000011248266674 \u0026v_{11} \u003c 0 \u0026\\dots r_{11} \\to b_{12} \u0026e\u0026=0,00048828 \\\\ a_{13}\u0026=1,4140625 \u0026r_{13}\u0026=1,41418457 \u0026b_{13}\u0026=1,41430664 \u0026f_{13}(a)\u0026=-0,00042725 \u0026f_{13}(r)\u0026=0,00026327 \u0026f_{13}(b)\u0026=-0,000082 \u0026v_{13}\u0026=0,00000003503464541 \u0026v_{12} \u003c 0 \u0026\\dots r_{12} \\to b_{13} \u0026e\u0026=0,00024414 \\\\ a_{14}\u0026=1,41418457 \u0026r_{14}\u0026=1,41424561 \u0026b_{14}\u0026=1,41430664 \u0026f_{14}(a)\u0026=-0,000082 \u0026f_{14}(r)\u0026=0,00026327 \u0026f_{14}(b)\u0026=0,00009063 \u0026v_{14}\u0026=-0,00000000743197098 \u0026v_{13} \u003e 0 \u0026\\dots r_{13} \\to a_{14} \u0026e\u0026=0,00012207 \\\\ a_{15}\u0026=1,41418457 \u0026r_{15}\u0026=1,41421509 \u0026b_{15}\u0026=1,41424561 \u0026f_{15}(a)\u0026=-0,000082 \u0026f_{15}(r)\u0026=0,00009063 \u0026f_{15}(b)\u0026=0,00000431 \u0026v_{15}\u0026=-0,00000000035381974 \u0026v_{14} \u003c 0 \u0026\\dots r_{14} \\to b_{15} \u0026e\u0026=0,00006104 \\\\ a_{16}\u0026=1,41418457 \u0026r_{16}\u0026=1,41419983 \u0026b_{16}\u0026=1,41421509 \u0026f_{16}(a)\u0026=-0,000082 \u0026f_{16}(r)\u0026=0,00000431 \u0026f_{16}(b)\u0026=-0,00003884 \u0026v_{16}\u0026=0,00000000318519861 \u0026v_{15} \u003c 0 \u0026\\dots r_{15} \\to b_{16} \u0026e\u0026=0,00003052 \\\\ a_{17}\u0026=1,41419983 \u0026r_{17}\u0026=1,41420746 \u0026b_{17}\u0026=1,41421509 \u0026f_{17}(a)\u0026=-0,00003884 \u0026f_{17}(r)\u0026=0,00000431 \u0026f_{17}(b)\u0026=-0,00001726 \u0026v_{17}\u0026=0,0000000006706049 \u0026v_{16} \u003e 0 \u0026\\dots r_{16} \\to a_{17} \u0026e\u0026=0,00001526 \\\\ a_{18}\u0026=1,41420746 \u0026r_{18}\u0026=1,41421127 \u0026b_{18}\u0026=1,41421509 \u0026f_{18}(a)\u0026=-0,00001726 \u0026f_{18}(r)\u0026=0,00000431 \u0026f_{18}(b)\u0026=-0,00000647 \u0026v_{18}\u0026=0,00000000011178264 \u0026v_{17} \u003e 0 \u0026\\dots r_{17} \\to a_{18} \u0026e\u0026=0,00000763 \\\\ a_{19}\u0026=1,41421127 \u0026r_{19}\u0026=1,41421318 \u0026b_{19}\u0026=1,41421509 \u0026f_{19}(a)\u0026=-0,00000647 \u0026f_{19}(r)\u0026=0,00000431 \u0026f_{19}(b)\u0026=-0,00000108 \u0026v_{19}\u0026=0,00000000000699263 \u0026v_{18} \u003e 0 \u0026\\dots r_{18} \\to a_{19} \u0026e\u0026=0,00000381 \\\\ a_{20}\u0026=1,41421318 \u0026r_{20}\u0026=1,41421413 \u0026b_{20}\u0026=1,41421509 \u0026f_{20}(a)\u0026=-0,00000108 \u0026f_{20}(r)\u0026=0,00000431 \u0026f_{20}(b)\u0026=0,00000162 \u0026v_{20}\u0026=-0,00000000000174678 \u0026v_{19} \u003e 0 \u0026\\dots r_{19} \\to a_{20} \u0026e\u0026=0,00000191 \\\\ a_{21}\u0026=1,41421318 \u0026r_{21}\u0026=1,41421366 \u0026b_{21}\u0026=1,41421413 \u0026f_{21}(a)\u0026=-0,00000108 \u0026f_{21}(r)\u0026=0,00000162 \u0026f_{21}(b)\u0026=0,00000027 \u0026v_{21}\u0026=-0,00000000000029021 \u0026v_{20} \u003c 0 \u0026\\dots r_{20} \\to b_{21} \u0026e\u0026=0,00000095 \\\\ a_{22}\u0026=1,41421318 \u0026r_{22}\u0026=1,41421342 \u0026b_{22}\u0026=1,41421366 \u0026f_{22}(a)\u0026=-0,00000108 \u0026f_{22}(r)\u0026=0,00000027 \u0026f_{22}(b)\u0026=-0,00000041 \u0026v_{22}\u0026=0,00000000000043807 \u0026v_{21} \u003c 0 \u0026\\dots r_{21} \\to b_{22} \u0026e\u0026=0,00000048 \\\\ a_{23}\u0026=1,41421342 \u0026r_{23}\u0026=1,41421354 \u0026b_{23}\u0026=1,41421366 \u0026f_{23}(a)\u0026=-0,00000041 \u0026f_{23}(r)\u0026=0,00000027 \u0026f_{23}(b)\u0026=-0,00000007 \u0026v_{23}\u0026=0,00000000000002777 \u0026v_{22} \u003e 0 \u0026\\dots r_{22} \\to a_{23} \u0026e\u0026=0,00000024 \\\\ a_{24}\u0026=1,41421354 \u0026r_{24}\u0026=1,4142136 \u0026b_{24}\u0026=1,41421366 \u0026f_{24}(a)\u0026=-0,00000007 \u0026f_{24}(r)\u0026=0,00000027 \u0026f_{24}(b)\u0026=0,0000001 \u0026v_{24}\u0026=-0,00000000000000685 \u0026v_{23} \u003e 0 \u0026\\dots r_{23} \\to a_{24} \u0026e\u0026=0,00000012 \\\\ a_{25}\u0026=1,41421354 \u0026r_{25}\u0026=1,41421357 \u0026b_{25}\u0026=1,4142136 \u0026f_{25}(a)\u0026=-0,00000007 \u0026f_{25}(r)\u0026=0,0000001 \u0026f_{25}(b)\u0026=0,00000002 \u0026v_{25}\u0026=-0,00000000000000108 \u0026v_{24} \u003c 0 \u0026\\dots r_{24} \\to b_{25} \u0026e\u0026=0,00000006 \\\\ a_{26}\u0026=1,41421354 \u0026r_{26}\u0026=1,41421355 \u0026b_{26}\u0026=1,41421357 \u0026f_{26}(a)\u0026=-0,00000007 \u0026f_{26}(r)\u0026=0,00000002 \u0026f_{26}(b)\u0026=-0,00000003 \u0026v_{26}\u0026=0,0000000000000018 \u0026v_{25} \u003c 0 \u0026\\dots r_{25} \\to b_{26} \u0026e\u0026=0,00000003 \\\\ a_{27}\u0026=1,41421355 \u0026r_{27}\u0026=1,41421356 \u0026b_{27}\u0026=1,41421357 \u0026f_{27}(a)\u0026=-0,00000003 \u0026f_{27}(r)\u0026=0,00000002 \u0026f_{27}(b)\u0026=-0,00000001 \u0026v_{27}\u0026=0,00000000000000014 \u0026v_{26} \u003e 0 \u0026\\dots r_{26} \\to a_{27} \u0026e\u0026=0,00000001 \\\\ a_{28}\u0026=1,41421356 \u0026r_{28}\u0026=1,41421356 \u0026b_{28}\u0026=1,41421357 \u0026f_{28}(a)\u0026=-0,00000001 \u0026f_{28}(r)\u0026=0,00000002 \u0026f_{28}(b)\u0026=0,00000001 \u0026v_{28}\u0026=-0,00000000000000003 \u0026v_{27} \u003e 0 \u0026\\dots r_{27} \\to a_{28} \u0026e\u0026=0,00000001 \\\\ a_{29}\u0026=1,41421356 \u0026r_{29}\u0026=1,41421356 \u0026b_{29}\u0026=1,41421356 \u0026f_{29}(a)\u0026=-0,00000001 \u0026f_{29}(r)\u0026=0,00000001 \u0026f_{29}(b)\u0026=0,0 \u0026v_{29}\u0026=0,0 \u0026v_{28} \u003c 0 \u0026\\dots r_{28} \\to b_{29} \u0026e\u0026=0,0 \\\\ \\\\ \u0026\u0026\\sqrt{2} \u0026= 1,4142135624 \\end{align*} $$ For \\(m=13\\) $$ \\begin{align} m \u0026= 13 \\\\ [a.b] \u0026= [0,13] \\\\ r_{0} \u0026= \\frac{0 + 13}{2} = 6.5 \u0026 \\text{initial result}\\\\ \\end{align} $$ $$ \\begin{align*} a_{0}\u0026=0,0 \u0026r_{0}\u0026=6,5 \u0026b_{0}\u0026=13,0 \u0026f_{0}(a)\u0026=-13,0 \u0026f_{0}(r)\u0026=156,0 \u0026f_{0}(b)\u0026=29,25 \u0026v_{0}\u0026=-380,25 \u0026 \u0026e\u0026=0,0 \\\\ a_{1}\u0026=0,0 \u0026r_{1}\u0026=3,25 \u0026b_{1}\u0026=6,5 \u0026f_{1}(a)\u0026=-13,0 \u0026f_{1}(r)\u0026=29,25 \u0026f_{1}(b)\u0026=-2,4375 \u0026v_{1}\u0026=31,6875 \u0026v_{0} \u003c 0 \u0026\\dots r_{0} \\to b_{1} \u0026e\u0026=6,5 \\\\ a_{2}\u0026=3,25 \u0026r_{2}\u0026=4,875 \u0026b_{2}\u0026=6,5 \u0026f_{2}(a)\u0026=-2,4375 \u0026f_{2}(r)\u0026=29,25 \u0026f_{2}(b)\u0026=10,765625 \u0026v_{2}\u0026=-26,2412109375 \u0026v_{1} \u003e 0 \u0026\\dots r_{1} \\to a_{2} \u0026e\u0026=3,25 \\\\ a_{3}\u0026=3,25 \u0026r_{3}\u0026=4,0625 \u0026b_{3}\u0026=4,875 \u0026f_{3}(a)\u0026=-2,4375 \u0026f_{3}(r)\u0026=10,765625 \u0026f_{3}(b)\u0026=3,50390625 \u0026v_{3}\u0026=-8,540771484375 \u0026v_{2} \u003c 0 \u0026\\dots r_{2} \\to b_{3} \u0026e\u0026=1,625 \\\\ a_{4}\u0026=3,25 \u0026r_{4}\u0026=3,65625 \u0026b_{4}\u0026=4,0625 \u0026f_{4}(a)\u0026=-2,4375 \u0026f_{4}(r)\u0026=3,50390625 \u0026f_{4}(b)\u0026=0,36816406 \u0026v_{4}\u0026=-0,89739990234375 \u0026v_{3} \u003c 0 \u0026\\dots r_{3} \\to b_{4} \u0026e\u0026=0,8125 \\\\ a_{5}\u0026=3,25 \u0026r_{5}\u0026=3,453125 \u0026b_{5}\u0026=3,65625 \u0026f_{5}(a)\u0026=-2,4375 \u0026f_{5}(r)\u0026=0,36816406 \u0026f_{5}(b)\u0026=-1,07592773 \u0026v_{5}\u0026=2,62257385253906 \u0026v_{4} \u003c 0 \u0026\\dots r_{4} \\to b_{5} \u0026e\u0026=0,40625 \\\\ a_{6}\u0026=3,453125 \u0026r_{6}\u0026=3,5546875 \u0026b_{6}\u0026=3,65625 \u0026f_{6}(a)\u0026=-1,07592773 \u0026f_{6}(r)\u0026=0,36816406 \u0026f_{6}(b)\u0026=-0,36419678 \u0026v_{6}\u0026=0,391849413514137 \u0026v_{5} \u003e 0 \u0026\\dots r_{5} \\to a_{6} \u0026e\u0026=0,203125 \\\\ a_{7}\u0026=3,5546875 \u0026r_{7}\u0026=3,60546875 \u0026b_{7}\u0026=3,65625 \u0026f_{7}(a)\u0026=-0,36419678 \u0026f_{7}(r)\u0026=0,36816406 \u0026f_{7}(b)\u0026=-0,00059509 \u0026v_{7}\u0026=0,00021673087030649 \u0026v_{6} \u003e 0 \u0026\\dots r_{6} \\to a_{7} \u0026e\u0026=0,1015625 \\\\ a_{8}\u0026=3,60546875 \u0026r_{8}\u0026=3,63085938 \u0026b_{8}\u0026=3,65625 \u0026f_{8}(a)\u0026=-0,00059509 \u0026f_{8}(r)\u0026=0,36816406 \u0026f_{8}(b)\u0026=0,1831398 \u0026v_{8}\u0026=-0,00010898517211899 \u0026v_{7} \u003e 0 \u0026\\dots r_{7} \\to a_{8} \u0026e\u0026=0,05078125 \\\\ a_{9}\u0026=3,60546875 \u0026r_{9}\u0026=3,61816406 \u0026b_{9}\u0026=3,63085938 \u0026f_{9}(a)\u0026=-0,00059509 \u0026f_{9}(r)\u0026=0,1831398 \u0026f_{9}(b)\u0026=0,09111118 \u0026v_{9}\u0026=-0,00005421960668173 \u0026v_{8} \u003c 0 \u0026\\dots r_{8} \\to b_{9} \u0026e\u0026=0,02539063 \\\\ a_{10}\u0026=3,60546875 \u0026r_{10}\u0026=3,61181641 \u0026b_{10}\u0026=3,61816406 \u0026f_{10}(a)\u0026=-0,00059509 \u0026f_{10}(r)\u0026=0,09111118 \u0026f_{10}(b)\u0026=0,04521775 \u0026v_{10}\u0026=-0,00002690875771805 \u0026v_{9} \u003c 0 \u0026\\dots r_{9} \\to b_{10} \u0026e\u0026=0,01269531 \\\\ a_{11}\u0026=3,60546875 \u0026r_{11}\u0026=3,60864258 \u0026b_{11}\u0026=3,61181641 \u0026f_{11}(a)\u0026=-0,00059509 \u0026f_{11}(r)\u0026=0,04521775 \u0026f_{11}(b)\u0026=0,02230126 \u0026v_{11}\u0026=-0,00001327131667495 \u0026v_{10} \u003c 0 \u0026\\dots r_{10} \\to b_{11} \u0026e\u0026=0,00634766 \\\\ a_{12}\u0026=3,60546875 \u0026r_{12}\u0026=3,60705566 \u0026b_{12}\u0026=3,60864258 \u0026f_{12}(a)\u0026=-0,00059509 \u0026f_{12}(r)\u0026=0,02230126 \u0026f_{12}(b)\u0026=0,01085056 \u0026v_{12}\u0026=-0,00000645709201308 \u0026v_{11} \u003c 0 \u0026\\dots r_{11} \\to b_{12} \u0026e\u0026=0,00317383 \\\\ a_{13}\u0026=3,60546875 \u0026r_{13}\u0026=3,60626221 \u0026b_{13}\u0026=3,60705566 \u0026f_{13}(a)\u0026=-0,00059509 \u0026f_{13}(r)\u0026=0,01085056 \u0026f_{13}(b)\u0026=0,00512711 \u0026v_{13}\u0026=-0,00000305110364707 \u0026v_{12} \u003c 0 \u0026\\dots r_{12} \\to b_{13} \u0026e\u0026=0,00158691 \\\\ a_{14}\u0026=3,60546875 \u0026r_{14}\u0026=3,60586548 \u0026b_{14}\u0026=3,60626221 \u0026f_{14}(a)\u0026=-0,00059509 \u0026f_{14}(r)\u0026=0,00512711 \u0026f_{14}(b)\u0026=0,00226585 \u0026v_{14}\u0026=-0,00000134839045529 \u0026v_{13} \u003c 0 \u0026\\dots r_{13} \\to b_{14} \u0026e\u0026=0,00079346 \\\\ a_{15}\u0026=3,60546875 \u0026r_{15}\u0026=3,60566711 \u0026b_{15}\u0026=3,60586548 \u0026f_{15}(a)\u0026=-0,00059509 \u0026f_{15}(r)\u0026=0,00226585 \u0026f_{15}(b)\u0026=0,00083534 \u0026v_{15}\u0026=-0,00000049710410721 \u0026v_{14} \u003c 0 \u0026\\dots r_{14} \\to b_{15} \u0026e\u0026=0,00039673 \\\\ a_{16}\u0026=3,60546875 \u0026r_{16}\u0026=3,60556793 \u0026b_{16}\u0026=3,60566711 \u0026f_{16}(a)\u0026=-0,00059509 \u0026f_{16}(r)\u0026=0,00083534 \u0026f_{16}(b)\u0026=0,00012011 \u0026v_{16}\u0026=-0,00000007147849512 \u0026v_{15} \u003c 0 \u0026\\dots r_{15} \\to b_{16} \u0026e\u0026=0,00019836 \\\\ a_{17}\u0026=3,60546875 \u0026r_{17}\u0026=3,60551834 \u0026b_{17}\u0026=3,60556793 \u0026f_{17}(a)\u0026=-0,00059509 \u0026f_{17}(r)\u0026=0,00012011 \u0026f_{17}(b)\u0026=-0,00023749 \u0026v_{17}\u0026=0,00000014132992043 \u0026v_{16} \u003c 0 \u0026\\dots r_{16} \\to b_{17} \u0026e\u0026=0,00009918 \\\\ a_{18}\u0026=3,60551834 \u0026r_{18}\u0026=3,60554314 \u0026b_{18}\u0026=3,60556793 \u0026f_{18}(a)\u0026=-0,00023749 \u0026f_{18}(r)\u0026=0,00012011 \u0026f_{18}(b)\u0026=-0,00005869 \u0026v_{18}\u0026=0,00000001393845341 \u0026v_{17} \u003e 0 \u0026\\dots r_{17} \\to a_{18} \u0026e\u0026=0,00004959 \\\\ a_{19}\u0026=3,60554314 \u0026r_{19}\u0026=3,60555553 \u0026b_{19}\u0026=3,60556793 \u0026f_{19}(a)\u0026=-0,00005869 \u0026f_{19}(r)\u0026=0,00012011 \u0026f_{19}(b)\u0026=0,00003071 \u0026v_{19}\u0026=-0,00000000180245487 \u0026v_{18} \u003e 0 \u0026\\dots r_{18} \\to a_{19} \u0026e\u0026=0,0000248 \\\\ a_{20}\u0026=3,60554314 \u0026r_{20}\u0026=3,60554934 \u0026b_{20}\u0026=3,60555553 \u0026f_{20}(a)\u0026=-0,00005869 \u0026f_{20}(r)\u0026=0,00003071 \u0026f_{20}(b)\u0026=-0,00001399 \u0026v_{20}\u0026=0,00000000082104112 \u0026v_{19} \u003c 0 \u0026\\dots r_{19} \\to b_{20} \u0026e\u0026=0,0000124 \\\\ a_{21}\u0026=3,60554934 \u0026r_{21}\u0026=3,60555243 \u0026b_{21}\u0026=3,60555553 \u0026f_{21}(a)\u0026=-0,00001399 \u0026f_{21}(r)\u0026=0,00003071 \u0026f_{21}(b)\u0026=0,00000836 \u0026v_{21}\u0026=-0,00000000011696509 \u0026v_{20} \u003e 0 \u0026\\dots r_{20} \\to a_{21} \u0026e\u0026=0,0000062 \\\\ a_{22}\u0026=3,60554934 \u0026r_{22}\u0026=3,60555089 \u0026b_{22}\u0026=3,60555243 \u0026f_{22}(a)\u0026=-0,00001399 \u0026f_{22}(r)\u0026=0,00000836 \u0026f_{22}(b)\u0026=-0,00000281 \u0026v_{22}\u0026=0,00000000003936945 \u0026v_{21} \u003c 0 \u0026\\dots r_{21} \\to b_{22} \u0026e\u0026=0,0000031 \\\\ a_{23}\u0026=3,60555089 \u0026r_{23}\u0026=3,60555166 \u0026b_{23}\u0026=3,60555243 \u0026f_{23}(a)\u0026=-0,00000281 \u0026f_{23}(r)\u0026=0,00000836 \u0026f_{23}(b)\u0026=0,00000277 \u0026v_{23}\u0026=-0,00000000000780489 \u0026v_{22} \u003e 0 \u0026\\dots r_{22} \\to a_{23} \u0026e\u0026=0,00000155 \\\\ a_{24}\u0026=3,60555089 \u0026r_{24}\u0026=3,60555127 \u0026b_{24}\u0026=3,60555166 \u0026f_{24}(a)\u0026=-0,00000281 \u0026f_{24}(r)\u0026=0,00000277 \u0026f_{24}(b)\u0026=-0,00000002 \u0026v_{24}\u0026=0,0000000000000575 \u0026v_{23} \u003c 0 \u0026\\dots r_{23} \\to b_{24} \u0026e\u0026=0,00000077 \\\\ a_{25}\u0026=3,60555127 \u0026r_{25}\u0026=3,60555147 \u0026b_{25}\u0026=3,60555166 \u0026f_{25}(a)\u0026=-0,00000002 \u0026f_{25}(r)\u0026=0,00000277 \u0026f_{25}(b)\u0026=0,00000138 \u0026v_{25}\u0026=-0,00000000000002812 \u0026v_{24} \u003e 0 \u0026\\dots r_{24} \\to a_{25} \u0026e\u0026=0,00000039 \\\\ a_{26}\u0026=3,60555127 \u0026r_{26}\u0026=3,60555137 \u0026b_{26}\u0026=3,60555147 \u0026f_{26}(a)\u0026=-0,00000002 \u0026f_{26}(r)\u0026=0,00000138 \u0026f_{26}(b)\u0026=0,00000068 \u0026v_{26}\u0026=-0,00000000000001385 \u0026v_{25} \u003c 0 \u0026\\dots r_{25} \\to b_{26} \u0026e\u0026=0,00000019 \\\\ a_{27}\u0026=3,60555127 \u0026r_{27}\u0026=3,60555132 \u0026b_{27}\u0026=3,60555137 \u0026f_{27}(a)\u0026=-0,00000002 \u0026f_{27}(r)\u0026=0,00000068 \u0026f_{27}(b)\u0026=0,00000033 \u0026v_{27}\u0026=-0,00000000000000672 \u0026v_{26} \u003c 0 \u0026\\dots r_{26} \\to b_{27} \u0026e\u0026=0,0000001 \\\\ a_{28}\u0026=3,60555127 \u0026r_{28}\u0026=3,6055513 \u0026b_{28}\u0026=3,60555132 \u0026f_{28}(a)\u0026=-0,00000002 \u0026f_{28}(r)\u0026=0,00000033 \u0026f_{28}(b)\u0026=0,00000015 \u0026v_{28}\u0026=-0,00000000000000315 \u0026v_{27} \u003c 0 \u0026\\dots r_{27} \\to b_{28} \u0026e\u0026=0,00000005 \\\\ a_{29}\u0026=3,60555127 \u0026r_{29}\u0026=3,60555128 \u0026b_{29}\u0026=3,6055513 \u0026f_{29}(a)\u0026=-0,00000002 \u0026f_{29}(r)\u0026=0,00000015 \u0026f_{29}(b)\u0026=0,00000007 \u0026v_{29}\u0026=-0,00000000000000137 \u0026v_{28} \u003c 0 \u0026\\dots r_{28} \\to b_{29} \u0026e\u0026=0,00000002 \\\\ a_{30}\u0026=3,60555127 \u0026r_{30}\u0026=3,60555128 \u0026b_{30}\u0026=3,60555128 \u0026f_{30}(a)\u0026=-0,00000002 \u0026f_{30}(r)\u0026=0,00000007 \u0026f_{30}(b)\u0026=0,00000002 \u0026v_{30}\u0026=-0,00000000000000047 \u0026v_{29} \u003c 0 \u0026\\dots r_{29} \\to b_{30} \u0026e\u0026=0,00000001 \\\\ a_{31}\u0026=3,60555127 \u0026r_{31}\u0026=3,60555128 \u0026b_{31}\u0026=3,60555128 \u0026f_{31}(a)\u0026=-0,00000002 \u0026f_{31}(r)\u0026=0,00000002 \u0026f_{31}(b)\u0026=0,0 \u0026v_{31}\u0026=-0,00000000000000003 \u0026v_{30} \u003c 0 \u0026\\dots r_{30} \\to b_{31} \u0026e\u0026=0,00000001 \\\\ a_{32}\u0026=3,60555127 \u0026r_{32}\u0026=3,60555127 \u0026b_{32}\u0026=3,60555128 \u0026f_{32}(a)\u0026=-0,00000002 \u0026f_{32}(r)\u0026=0,0 \u0026f_{32}(b)\u0026=-0,00000001 \u0026v_{32}\u0026=0,00000000000000019 \u0026v_{31} \u003c 0 \u0026\\dots r_{31} \\to b_{32} \u0026e\u0026=0,0 \\\\ a_{33}\u0026=3,60555127 \u0026r_{33}\u0026=3,60555127 \u0026b_{33}\u0026=3,60555128 \u0026f_{33}(a)\u0026=-0,00000001 \u0026f_{33}(r)\u0026=0,0 \u0026f_{33}(b)\u0026=0,0 \u0026v_{33}\u0026=0,00000000000000004 \u0026v_{32} \u003e 0 \u0026\\dots r_{32} \\to a_{33} \u0026e\u0026=0,0 \\\\ a_{34}\u0026=3,60555127 \u0026r_{34}\u0026=3,60555128 \u0026b_{34}\u0026=3,60555128 \u0026f_{34}(a)\u0026=0,0 \u0026f_{34}(r)\u0026=0,0 \u0026f_{34}(b)\u0026=0,0 \u0026v_{34}\u0026=0,00000000000000001 \u0026v_{33} \u003e 0 \u0026\\dots r_{33} \\to a_{34} \u0026e\u0026=0,0 \\\\ a_{35}\u0026=3,60555128 \u0026r_{35}\u0026=3,60555128 \u0026b_{35}\u0026=3,60555128 \u0026f_{35}(a)\u0026=0,0 \u0026f_{35}(r)\u0026=0,0 \u0026f_{35}(b)\u0026=0,0 \u0026v_{35}\u0026=0,0 \u0026v_{34} \u003e 0 \u0026\\dots r_{34} \\to a_{35} \u0026e\u0026=0,0 \\\\ \\\\ \u0026\u0026\\sqrt{13} \u0026= 3,60555128 \\end{align*} $$For \\(m=354\\) $$ \\begin{align} m \u0026= 354 \\\\ [a.b] \u0026= [0,354] \\\\ r_{0} \u0026= \\frac{0 + 354}{2} = 177 \u0026 \\text{initial result}\\\\ \\end{align} $$ $$ \\begin{align*} a_{0}\u0026=0,0 \u0026r_{0}\u0026=177,0 \u0026b_{0}\u0026=354,0 \u0026f_{0}(a)\u0026=-354,0 \u0026f_{0}(r)\u0026=124962,0 \u0026f_{0}(b)\u0026=30975,0 \u0026v_{0}\u0026=-10965150,0 \u0026 \u0026e\u0026=0,0 \\\\ a_{1}\u0026=0,0 \u0026r_{1}\u0026=88,5 \u0026b_{1}\u0026=177,0 \u0026f_{1}(a)\u0026=-354,0 \u0026f_{1}(r)\u0026=30975,0 \u0026f_{1}(b)\u0026=7478,25 \u0026v_{1}\u0026=-2647300,5 \u0026v_{0} \u003c 0 \u0026\\dots r_{0} \\to b_{1} \u0026e\u0026=177,0 \\\\ a_{2}\u0026=0,0 \u0026r_{2}\u0026=44,25 \u0026b_{2}\u0026=88,5 \u0026f_{2}(a)\u0026=-354,0 \u0026f_{2}(r)\u0026=7478,25 \u0026f_{2}(b)\u0026=1604,0625 \u0026v_{2}\u0026=-567838,125 \u0026v_{1} \u003c 0 \u0026\\dots r_{1} \\to b_{2} \u0026e\u0026=88,5 \\\\ a_{3}\u0026=0,0 \u0026r_{3}\u0026=22,125 \u0026b_{3}\u0026=44,25 \u0026f_{3}(a)\u0026=-354,0 \u0026f_{3}(r)\u0026=1604,0625 \u0026f_{3}(b)\u0026=135,515625 \u0026v_{3}\u0026=-47972,53125 \u0026v_{2} \u003c 0 \u0026\\dots r_{2} \\to b_{3} \u0026e\u0026=44,25 \\\\ a_{4}\u0026=0,0 \u0026r_{4}\u0026=11,0625 \u0026b_{4}\u0026=22,125 \u0026f_{4}(a)\u0026=-354,0 \u0026f_{4}(r)\u0026=135,515625 \u0026f_{4}(b)\u0026=-231,62109375 \u0026v_{4}\u0026=81993,8671875 \u0026v_{3} \u003c 0 \u0026\\dots r_{3} \\to b_{4} \u0026e\u0026=22,125 \\\\ a_{5}\u0026=11,0625 \u0026r_{5}\u0026=16,59375 \u0026b_{5}\u0026=22,125 \u0026f_{5}(a)\u0026=-231,62109375 \u0026f_{5}(r)\u0026=135,515625 \u0026f_{5}(b)\u0026=-78,64746094 \u0026v_{5}\u0026=18216,4109230042 \u0026v_{4} \u003e 0 \u0026\\dots r_{4} \\to a_{5} \u0026e\u0026=11,0625 \\\\ a_{6}\u0026=16,59375 \u0026r_{6}\u0026=19,359375 \u0026b_{6}\u0026=22,125 \u0026f_{6}(a)\u0026=-78,64746094 \u0026f_{6}(r)\u0026=135,515625 \u0026f_{6}(b)\u0026=20,78540039 \u0026v_{6}\u0026=-1634,71896529198 \u0026v_{5} \u003e 0 \u0026\\dots r_{5} \\to a_{6} \u0026e\u0026=5,53125 \\\\ a_{7}\u0026=16,59375 \u0026r_{7}\u0026=17,9765625 \u0026b_{7}\u0026=19,359375 \u0026f_{7}(a)\u0026=-78,64746094 \u0026f_{7}(r)\u0026=20,78540039 \u0026f_{7}(b)\u0026=-30,84320068 \u0026v_{7}\u0026=2425,73942095041 \u0026v_{6} \u003c 0 \u0026\\dots r_{6} \\to b_{7} \u0026e\u0026=2,765625 \\\\ a_{8}\u0026=17,9765625 \u0026r_{8}\u0026=18,66796875 \u0026b_{8}\u0026=19,359375 \u0026f_{8}(a)\u0026=-30,84320068 \u0026f_{8}(r)\u0026=20,78540039 \u0026f_{8}(b)\u0026=-5,50694275 \u0026v_{8}\u0026=169,851740361191 \u0026v_{7} \u003e 0 \u0026\\dots r_{7} \\to a_{8} \u0026e\u0026=1,3828125 \\\\ a_{9}\u0026=18,66796875 \u0026r_{9}\u0026=19,01367188 \u0026b_{9}\u0026=19,359375 \u0026f_{9}(a)\u0026=-5,50694275 \u0026f_{9}(r)\u0026=20,78540039 \u0026f_{9}(b)\u0026=7,51971817 \u0026v_{9}\u0026=-41,4106574518955 \u0026v_{8} \u003e 0 \u0026\\dots r_{8} \\to a_{9} \u0026e\u0026=0,69140625 \\\\ a_{10}\u0026=18,66796875 \u0026r_{10}\u0026=18,84082031 \u0026b_{10}\u0026=19,01367188 \u0026f_{10}(a)\u0026=-5,50694275 \u0026f_{10}(r)\u0026=7,51971817 \u0026f_{10}(b)\u0026=0,97651005 \u0026v_{10}\u0026=-5,37758492770081 \u0026v_{9} \u003c 0 \u0026\\dots r_{9} \\to b_{10} \u0026e\u0026=0,34570313 \\\\ a_{11}\u0026=18,66796875 \u0026r_{11}\u0026=18,75439453 \u0026b_{11}\u0026=18,84082031 \u0026f_{11}(a)\u0026=-5,50694275 \u0026f_{11}(r)\u0026=0,97651005 \u0026f_{11}(b)\u0026=-2,27268577 \u0026v_{11}\u0026=12,5155504010945 \u0026v_{10} \u003c 0 \u0026\\dots r_{10} \\to b_{11} \u0026e\u0026=0,17285156 \\\\ a_{12}\u0026=18,75439453 \u0026r_{12}\u0026=18,79760742 \u0026b_{12}\u0026=18,84082031 \u0026f_{12}(a)\u0026=-2,27268577 \u0026f_{12}(r)\u0026=0,97651005 \u0026f_{12}(b)\u0026=-0,64995521 \u0026v_{12}\u0026=1,47714396142455 \u0026v_{11} \u003e 0 \u0026\\dots r_{11} \\to a_{12} \u0026e\u0026=0,08642578 \\\\ a_{13}\u0026=18,79760742 \u0026r_{13}\u0026=18,81921387 \u0026b_{13}\u0026=18,84082031 \u0026f_{13}(a)\u0026=-0,64995521 \u0026f_{13}(r)\u0026=0,97651005 \u0026f_{13}(b)\u0026=0,16281058 \u0026v_{13}\u0026=-0,105819584526478 \u0026v_{12} \u003e 0 \u0026\\dots r_{12} \\to a_{13} \u0026e\u0026=0,04321289 \\\\ a_{14}\u0026=18,79760742 \u0026r_{14}\u0026=18,80841064 \u0026b_{14}\u0026=18,81921387 \u0026f_{14}(a)\u0026=-0,64995521 \u0026f_{14}(r)\u0026=0,16281058 \u0026f_{14}(b)\u0026=-0,24368903 \u0026v_{14}\u0026=0,158386953260919 \u0026v_{13} \u003c 0 \u0026\\dots r_{13} \\to b_{14} \u0026e\u0026=0,02160645 \\\\ a_{15}\u0026=18,80841064 \u0026r_{15}\u0026=18,81381226 \u0026b_{15}\u0026=18,81921387 \u0026f_{15}(a)\u0026=-0,24368903 \u0026f_{15}(r)\u0026=0,16281058 \u0026f_{15}(b)\u0026=-0,0404684 \u0026v_{15}\u0026=0,00986170531828501 \u0026v_{14} \u003e 0 \u0026\\dots r_{14} \\to a_{15} \u0026e\u0026=0,01080322 \\\\ a_{16}\u0026=18,81381226 \u0026r_{16}\u0026=18,81651306 \u0026b_{16}\u0026=18,81921387 \u0026f_{16}(a)\u0026=-0,0404684 \u0026f_{16}(r)\u0026=0,16281058 \u0026f_{16}(b)\u0026=0,06116379 \u0026v_{16}\u0026=-0,00247520097863952 \u0026v_{15} \u003e 0 \u0026\\dots r_{15} \\to a_{16} \u0026e\u0026=0,00540161 \\\\ a_{17}\u0026=18,81381226 \u0026r_{17}\u0026=18,81516266 \u0026b_{17}\u0026=18,81651306 \u0026f_{17}(a)\u0026=-0,0404684 \u0026f_{17}(r)\u0026=0,06116379 \u0026f_{17}(b)\u0026=0,01034587 \u0026v_{17}\u0026=-0,00041868094073607 \u0026v_{16} \u003c 0 \u0026\\dots r_{16} \\to b_{17} \u0026e\u0026=0,00270081 \\\\ a_{18}\u0026=18,81381226 \u0026r_{18}\u0026=18,81448746 \u0026b_{18}\u0026=18,81516266 \u0026f_{18}(a)\u0026=-0,0404684 \u0026f_{18}(r)\u0026=0,01034587 \u0026f_{18}(b)\u0026=-0,01506172 \u0026v_{18}\u0026=0,00060952372995326 \u0026v_{17} \u003c 0 \u0026\\dots r_{17} \\to b_{18} \u0026e\u0026=0,0013504 \\\\ a_{19}\u0026=18,81448746 \u0026r_{19}\u0026=18,81482506 \u0026b_{19}\u0026=18,81516266 \u0026f_{19}(a)\u0026=-0,01506172 \u0026f_{19}(r)\u0026=0,01034587 \u0026f_{19}(b)\u0026=-0,00235804 \u0026v_{19}\u0026=0,00003551610033706 \u0026v_{18} \u003e 0 \u0026\\dots r_{18} \\to a_{19} \u0026e\u0026=0,0006752 \\\\ a_{20}\u0026=18,81482506 \u0026r_{20}\u0026=18,81499386 \u0026b_{20}\u0026=18,81516266 \u0026f_{20}(a)\u0026=-0,00235804 \u0026f_{20}(r)\u0026=0,01034587 \u0026f_{20}(b)\u0026=0,00399389 \u0026v_{20}\u0026=-0,00000941774059949 \u0026v_{19} \u003e 0 \u0026\\dots r_{19} \\to a_{20} \u0026e\u0026=0,0003376 \\\\ a_{21}\u0026=18,81482506 \u0026r_{21}\u0026=18,81490946 \u0026b_{21}\u0026=18,81499386 \u0026f_{21}(a)\u0026=-0,00235804 \u0026f_{21}(r)\u0026=0,00399389 \u0026f_{21}(b)\u0026=0,00081792 \u0026v_{21}\u0026=-0,00000192868312397 \u0026v_{20} \u003c 0 \u0026\\dots r_{20} \\to b_{21} \u0026e\u0026=0,0001688 \\\\ a_{22}\u0026=18,81482506 \u0026r_{22}\u0026=18,81486726 \u0026b_{22}\u0026=18,81490946 \u0026f_{22}(a)\u0026=-0,00235804 \u0026f_{22}(r)\u0026=0,00081792 \u0026f_{22}(b)\u0026=-0,00077006 \u0026v_{22}\u0026=0,00000181583301588 \u0026v_{21} \u003c 0 \u0026\\dots r_{21} \\to b_{22} \u0026e\u0026=0,0000844 \\\\ a_{23}\u0026=18,81486726 \u0026r_{23}\u0026=18,81488836 \u0026b_{23}\u0026=18,81490946 \u0026f_{23}(a)\u0026=-0,00077006 \u0026f_{23}(r)\u0026=0,00081792 \u0026f_{23}(b)\u0026=0,00002393 \u0026v_{23}\u0026=-0,00000001842631129 \u0026v_{22} \u003e 0 \u0026\\dots r_{22} \\to a_{23} \u0026e\u0026=0,0000422 \\\\ a_{24}\u0026=18,81486726 \u0026r_{24}\u0026=18,81487781 \u0026b_{24}\u0026=18,81488836 \u0026f_{24}(a)\u0026=-0,00077006 \u0026f_{24}(r)\u0026=0,00002393 \u0026f_{24}(b)\u0026=-0,00037307 \u0026v_{24}\u0026=0,00000028728400509 \u0026v_{23} \u003c 0 \u0026\\dots r_{23} \\to b_{24} \u0026e\u0026=0,0000211 \\\\ a_{25}\u0026=18,81487781 \u0026r_{25}\u0026=18,81488308 \u0026b_{25}\u0026=18,81488836 \u0026f_{25}(a)\u0026=-0,00037307 \u0026f_{25}(r)\u0026=0,00002393 \u0026f_{25}(b)\u0026=-0,00017457 \u0026v_{25}\u0026=0,00000006512587636 \u0026v_{24} \u003e 0 \u0026\\dots r_{24} \\to a_{25} \u0026e\u0026=0,00001055 \\\\ a_{26}\u0026=18,81488308 \u0026r_{26}\u0026=18,81488572 \u0026b_{26}\u0026=18,81488836 \u0026f_{26}(a)\u0026=-0,00017457 \u0026f_{26}(r)\u0026=0,00002393 \u0026f_{26}(b)\u0026=-0,00007532 \u0026v_{26}\u0026=0,00000001314860687 \u0026v_{25} \u003e 0 \u0026\\dots r_{25} \\to a_{26} \u0026e\u0026=0,00000528 \\\\ a_{27}\u0026=18,81488572 \u0026r_{27}\u0026=18,81488704 \u0026b_{27}\u0026=18,81488836 \u0026f_{27}(a)\u0026=-0,00007532 \u0026f_{27}(r)\u0026=0,00002393 \u0026f_{27}(b)\u0026=-0,0000257 \u0026v_{27}\u0026=0,00000000193543172 \u0026v_{26} \u003e 0 \u0026\\dots r_{26} \\to a_{27} \u0026e\u0026=0,00000264 \\\\ a_{28}\u0026=18,81488704 \u0026r_{28}\u0026=18,8148877 \u0026b_{28}\u0026=18,81488836 \u0026f_{28}(a)\u0026=-0,0000257 \u0026f_{28}(r)\u0026=0,00002393 \u0026f_{28}(b)\u0026=-0,00000088 \u0026v_{28}\u0026=0,0000000000227104 \u0026v_{27} \u003e 0 \u0026\\dots r_{27} \\to a_{28} \u0026e\u0026=0,00000132 \\\\ a_{29}\u0026=18,8148877 \u0026r_{29}\u0026=18,81488803 \u0026b_{29}\u0026=18,81488836 \u0026f_{29}(a)\u0026=-0,00000088 \u0026f_{29}(r)\u0026=0,00002393 \u0026f_{29}(b)\u0026=0,00001152 \u0026v_{29}\u0026=-0,00000000001018352 \u0026v_{28} \u003e 0 \u0026\\dots r_{28} \\to a_{29} \u0026e\u0026=0,00000066 \\\\ a_{30}\u0026=18,8148877 \u0026r_{30}\u0026=18,81488786 \u0026b_{30}\u0026=18,81488803 \u0026f_{30}(a)\u0026=-0,00000088 \u0026f_{30}(r)\u0026=0,00001152 \u0026f_{30}(b)\u0026=0,00000532 \u0026v_{30}\u0026=-0,0000000000047012 \u0026v_{29} \u003c 0 \u0026\\dots r_{29} \\to b_{30} \u0026e\u0026=0,00000033 \\\\ a_{31}\u0026=18,8148877 \u0026r_{31}\u0026=18,81488778 \u0026b_{31}\u0026=18,81488786 \u0026f_{31}(a)\u0026=-0,00000088 \u0026f_{31}(r)\u0026=0,00000532 \u0026f_{31}(b)\u0026=0,00000222 \u0026v_{31}\u0026=-0,00000000000196004 \u0026v_{30} \u003c 0 \u0026\\dots r_{30} \\to b_{31} \u0026e\u0026=0,00000016 \\\\ a_{32}\u0026=18,8148877 \u0026r_{32}\u0026=18,81488774 \u0026b_{32}\u0026=18,81488778 \u0026f_{32}(a)\u0026=-0,00000088 \u0026f_{32}(r)\u0026=0,00000222 \u0026f_{32}(b)\u0026=0,00000067 \u0026v_{32}\u0026=-0,00000000000058946 \u0026v_{31} \u003c 0 \u0026\\dots r_{31} \\to b_{32} \u0026e\u0026=0,00000008 \\\\ a_{33}\u0026=18,8148877 \u0026r_{33}\u0026=18,81488772 \u0026b_{33}\u0026=18,81488774 \u0026f_{33}(a)\u0026=-0,00000088 \u0026f_{33}(r)\u0026=0,00000067 \u0026f_{33}(b)\u0026=-0,00000011 \u0026v_{33}\u0026=0,00000000000009583 \u0026v_{32} \u003c 0 \u0026\\dots r_{32} \\to b_{33} \u0026e\u0026=0,00000004 \\\\ a_{34}\u0026=18,81488772 \u0026r_{34}\u0026=18,81488773 \u0026b_{34}\u0026=18,81488774 \u0026f_{34}(a)\u0026=-0,00000011 \u0026f_{34}(r)\u0026=0,00000067 \u0026f_{34}(b)\u0026=0,00000028 \u0026v_{34}\u0026=-0,00000000000003028 \u0026v_{33} \u003e 0 \u0026\\dots r_{33} \\to a_{34} \u0026e\u0026=0,00000002 \\\\ a_{35}\u0026=18,81488772 \u0026r_{35}\u0026=18,81488772 \u0026b_{35}\u0026=18,81488773 \u0026f_{35}(a)\u0026=-0,00000011 \u0026f_{35}(r)\u0026=0,00000028 \u0026f_{35}(b)\u0026=0,00000009 \u0026v_{35}\u0026=-0,00000000000000926 \u0026v_{34} \u003c 0 \u0026\\dots r_{34} \\to b_{35} \u0026e\u0026=0,00000001 \\\\ a_{36}\u0026=18,81488772 \u0026r_{36}\u0026=18,81488772 \u0026b_{36}\u0026=18,81488772 \u0026f_{36}(a)\u0026=-0,00000011 \u0026f_{36}(r)\u0026=0,00000009 \u0026f_{36}(b)\u0026=-0,00000001 \u0026v_{36}\u0026=0,00000000000000125 \u0026v_{35} \u003c 0 \u0026\\dots r_{35} \\to b_{36} \u0026e\u0026=0,00000001 \\\\ a_{37}\u0026=18,81488772 \u0026r_{37}\u0026=18,81488772 \u0026b_{37}\u0026=18,81488772 \u0026f_{37}(a)\u0026=-0,00000001 \u0026f_{37}(r)\u0026=0,00000009 \u0026f_{37}(b)\u0026=0,00000004 \u0026v_{37}\u0026=-0,00000000000000043 \u0026v_{36} \u003e 0 \u0026\\dots r_{36} \\to a_{37} \u0026e\u0026=0,0 \\\\ \\\\ \u0026\u0026\\sqrt{354}\u0026=18,81488772 \\end{align*} $$ 2. Newton-Raphson The Newton-Raphson method is an efficient and widely used numerical technique for finding approximate solutions to equations of the form \\(f(x) = 0\\). It is particularly effective for equations that are difficult or impossible to solve algebraically. The method uses an iterative approach, starting with an initial guess for the root and refining this estimate with each step.\nHow it works At its core, the Newton-Raphson method relies on the concept of tangent lines. For a given function \\(f(x)\\)), the method approximates the root by finding the point where the tangent to the curve at a given \\(x_n\\)​ intersects the \\(x\\)-axis. Mathematically, the iteration formula is expressed as: $$ x_{n+1}=x_{n}-\\frac{f(x_{n})}{f'(x_{n})} $$ Here:\n\\(x_n\\)​ is the current approximation of the root. \\(f(x_n)\\) is the value of the function at \\(x_n\\)​. \\(f'(x_n)\\) is the derivative of the function at \\(x_n\\)​, which represents the slope of the tangent. The process is repeated until the successive approximations converge to a value within a desired level of accuracy.\nUse case: Square root $$ \\begin{align*} x\u0026=\\sqrt{m} \u0026\\text{define x as the square root of m} \\\\ x^2\u0026=m \u0026\\text{squaring both sides to remove the square root} \\\\ x^2-m\u0026=0 \u0026\\text{rearrange to express the equation in standard form} \\\\ f(x)\u0026=x^2-m \u0026\\text{define f(x) as the fucntion whose root we seek} \\\\ f'(x)\u0026=2x \u0026\\text{the derivative, which we will need in this exercise} \\end{align*} $$replacing at the general formula $$ \\begin{align*} x_{n+1}\u0026=x_{n}-\\frac{x_{n}^2-m}{2x_{n}} \\\\ \\end{align*} $$ we can simplify the expression a bit $$ \\begin{align*} \u0026=x_{n}-\\frac{x_{n}^2-m}{2x_{n}} \\\\ \u0026\u0026\\text{apply the fraction property: } a-\\frac{b}{c}=\\frac{ac-b}{c} \\\\ \u0026=\\frac{x_{n}.2x_{n}-(x_{n}^2-m)}{2x_{n}} \\\\ \u0026\u0026\\text{simplify the numerator }x_{n}.2x_{n} \\to 2x_{n}^2 \\\\ \u0026=\\frac{2x_{n}^2-(x_{n}^2-m)}{2x_{n}} \\\\ \u0026\u0026\\text{distribute negative sign and combine like terms} \\\\ \u0026\u00262x_{n}^2-(x_{n}^2-m) \\to 2x_{n}^2-x_{n}^2+m \\to x_{n}^2+m \\\\ \u0026=\\frac{x_{n}^2+m}{2x_{n}} \u0026\\text{final simplified form}\\\\ \\end{align*} $$ so we now have a simpler formula to work with $$ x_{n+1}=\\frac{x_{n}^2+m}{2x_{n}} $$Let\u0026rsquo;s find some roots For \\(m=2\\) means we want to get the result for this equation: \\(x=\\sqrt{m}\\), also let\u0026rsquo;s take the same value for the starting guest, which for this particular scenario it\u0026rsquo;s a safe guest. $$ \\begin{align*} m \u0026= 2 \\\\ x_0 \u0026= m \\to 2 \\\\ \\\\ \u0026\\text{Iteration} \u0026\\text{Result} \u0026 \u0026\\text{Error} \\\\ x_1 \u0026= \\frac{x_{0}^2+m}{2x_{0}} \u0026\\to \\frac{2,0^2+2}{2\\times2,0} \u0026= 1,5 \u0026 x_0-x_1 \u0026= 0,5\\\\ x_2 \u0026= \\frac{x_{1}^2+m}{2x_{1}} \u0026\\to \\frac{1,5^2+2}{2\\times1,5} \u0026= 1,4166666667 \u0026 x_1-x_2 \u0026= 0,0833333333 \\\\ x_3 \u0026= \\frac{x_{2}^2+m}{2x_{2}} \u0026\\to \\frac{1,4166666667^2+2}{2\\times1,4166666667} \u0026= 1,4142156863 \u0026 x_2-x_3 \u0026= 0,0024509804 \\\\ x_4\u0026=\\frac{x_{3}^2+m}{2x_{3}} \u0026\\to \\frac{1,4142156863^2+2}{2\\times1,4142156863} \u0026= 1,4142135624 \u0026 x_3-x_4\u0026=0,0000021239\\\\ x_5\u0026=\\frac{x_{4}^2+m}{2x_{4}}\u0026\\to \\frac{1,4142135624^2+2}{2\\times1,4142135624} \u0026= 1,4142135624 \u0026 x_4-x_5\u0026=0,0 \\\\ \\\\ \u0026\u0026\\sqrt{2} \u0026= 1,4142135624 \\end{align*} $$For \\(m=13\\) $$ \\begin{align*} m \u0026= 13 \\\\ x_0 \u0026= m \\to 13 \\\\ \\\\ \u0026\\text{Iteration} \u0026\\text{Result} \u0026 \u0026\\text{Error} \\\\ x_1 \u0026= \\frac{x_{0}^2+m}{2x_{0}} \\to \u0026\\frac{13,0^2+13}{2\\times13,0} \u0026= 7,0 \u0026 x_0-x_1 \u0026=6,0\\\\ x_2 \u0026= \\frac{x_{1}^2+m}{2x_{1}} \\to \u0026\\frac{7,0^2+13}{2\\times7,0} \u0026= 4,4285714286 \u0026 x_1-x_2\u0026=2,5714285714\\\\ x_3 \u0026= \\frac{x_{2}^2+m}{2x_{2}} \\to \u0026\\frac{4,4285714286^2+13}{2\\times4,4285714286} \u0026= 3,6820276498 \u0026 x_2-x_3\u0026=0,7465437788\\\\ x_4 \u0026= \\frac{x_{3}^2+m}{2x_{3}} \\to \u0026\\frac{3,6820276498^2+13}{2\\times3,6820276498} \u0026= 3,6063454895 \u0026 x_3-x_4\u0026=0,0756821603\\\\ x_5 \u0026= \\frac{x_{4}^2+m}{2x_{4}} \\to \u0026\\frac{3,6063454895^2+13}{2\\times3,6063454895} \u0026= 3,6055513629 \u0026 x_4-x_5\u0026=0,0007941265\\\\ x_6 \u0026= \\frac{x_{5}^2+m}{2x_{5}} \\to \u0026\\frac{3,6055513629^2+13}{2\\times3,6055513629} \u0026= 3,6055512755 \u0026 x_5-x_6\u0026=0,0000000875\\\\ x_7 \u0026= \\frac{x_{6}^2+m}{2x_{6}} \\to \u0026\\frac{3,6055512755^2+13}{2\\times3,6055512755} \u0026= 3,6055512755 \u0026 x_6-x_7\u0026=0,0\\\\ \\\\ \u0026\u0026\\sqrt{13}\u0026=3,6055512755 \\end{align*} $$For \\(m=354\\) $$ \\begin{align*} m \u0026= 354 \\\\ x_0 \u0026= m \\to 354 \\\\ \\\\ \u0026\\text{Iteration} \u0026\\text{Result} \u0026 \u0026\\text{Error} \\\\ x_1 \u0026= \\frac{x_{0}^2+m}{2x_{0}} \u0026\\to \\frac{354,0^2+354}{2\\times354,0} \u0026= 177,5 \u0026 x_0-x_1\u0026=176,5\\\\ x_2 \u0026= \\frac{x_{1}^2+m}{2x_{1}} \u0026\\to \\frac{177,5^2+354}{2\\times177,5} \u0026= 89,7471830986 \u0026 x_1-x_2\u0026=87,7528169014\\\\ x_3 \u0026= \\frac{x_{2}^2+m}{2x_{2}} \u0026\\to \\frac{89,7471830986^2+354}{2\\times89,7471830986} \u0026= 46,8457982959 \u0026 x_2-x_3 \u0026= 42,9013848026\\\\ x_4 \u0026= \\frac{x_{3}^2+m}{2x_{3}} \u0026\\to \\frac{46,8457982959^2+354}{2\\times46,8457982959} \u0026= 27,2012529479 \u0026 x_3-x_4 \u0026= 19,6445453481\\\\ x_5 \u0026= \\frac{x_{4}^2+m}{2x_{4}} \u0026\\to \\frac{27,2012529479^2+354}{2\\times27,2012529479} \u0026= 20,1076796725 \u0026 x_4-x_5 \u0026= 7,0935732753\\\\ x_6 \u0026= \\frac{x_{5}^2+m}{2x_{5}} \u0026\\to \\frac{20,1076796725^2+354}{2\\times20,1076796725} \u0026= 18,8564467448 \u0026 x_5-x_6 \u0026= 1,2512329277\\\\ x_7 \u0026= \\frac{x_{6}^2+m}{2x_{6}} \u0026\\to \\frac{18,8564467448^2+354}{2\\times18,8564467448} \u0026= 18,8149335196 \u0026 x_6-x_7 \u0026= 0,0415132252\\\\ x_8 \u0026= \\frac{x_{7}^2+m}{2x_{7}} \u0026\\to \\frac{18,8149335196^2+354}{2\\times18,8149335196} \u0026= 18,8148877223 \u0026 x_7-x_8 \u0026= 0,0000457973\\\\ x_9 \u0026= \\frac{x_{8}^2+m}{2x_{8}} \u0026\\to \\frac{18,8148877223^2+354}{2\\times18,8148877223} \u0026= 18,8148877222 \u0026 x_8-x_9 \u0026= 0,0000000001\\\\ x_{10} \u0026= \\frac{x_{9}^2+m}{2x_{9}} \u0026\\to \\frac{18,8148877222^2+354}{2\\times18,8148877222} \u0026= 18,8148877222 \u0026 x_9-x_{10} \u0026= 0,0\\\\ \\\\ \u0026\u0026\\sqrt{354} \u0026= 18,8148877222 \\end{align*} $$ 3. Secant The secant method is a numerical algorithm used to approximate solutions to equations of the form \\(f(x) = 0\\). It is similar to the Newton-Raphson method but does not require the explicit computation of the derivative of \\(f(x)\\). Instead, the secant method uses a finite difference approximation of the derivative, making it a practical choice when the derivative is difficult or costly to calculate.\nHow It Works: The secant method starts with two initial approximations, \\(x_0\\) and \\(x_1\\)​, for the root of \\(f(x) = 0\\). These approximations are used to compute a new estimate, \\(x_{2}\\)​, by intersecting the secant line (the line passing through )(x_0, f(x_0))\\( and \\)(x_1, f(x_1))\\( with the \\)x$-axis. The formula for updating the estimate is: $$ x_{n+1} = x_n - \\frac{f(x_n)(x_n - x_{n-1})}{f(x_n) - f(x_{n-1})} $$ Here:\n\\(x_n\\) and \\(x_{n-1}\\)​ are the two most recent estimates of the root. \\(f(x_n)\\) and \\(f(x_{n-1})\\) are the function values at these points. This process is repeated until the difference between successive approximations is smaller than a predefined tolerance or until the function value at the current estimate is sufficiently close to zero.\nUse case: Square root For \\(m=2\\) $$ \\begin{align} m \u0026= 2 \\\\ f(x) \u0026= x^2 - m \\\\ x0_{0} \u0026= m \\\\ x1_{0} \u0026= m-1 \\\\ x2_{n} \u0026= x1_{n} - \\frac{f(x1_{n})(x1_{n} - x0_{n})}{f(x1_{n}) - f(x0_{n})} \\\\ x0_{n+1} \u0026= x1_{n} \\\\ x1_{n+1} \u0026= x2_{n} \\\\ \\end{align} $$$$ \\begin{align} x0_{0}\u0026=2,0 \u0026x1_{0}\u0026=1,0 \u0026x2_{0}\u0026=1,33333333 \u0026fx0_{0}\u0026=2,0 \u0026fx1_{0}\u0026=-1,0 \u0026e_{0}\u0026=0,33333333\\\\ x0_{1}\u0026=1,0 \u0026x1_{1}\u0026=1,33333333 \u0026x2_{1}\u0026=1,42857143 \u0026fx0_{1}\u0026=-1,0 \u0026fx1_{1}\u0026=-0,22222222 \u0026e_{1}\u0026=0,0952381\\\\ x0_{2}\u0026=1,33333333 \u0026x1_{2}\u0026=1,42857143 \u0026x2_{2}\u0026=1,4137931 \u0026fx0_{2}\u0026=-0,22222222 \u0026fx1_{2}\u0026=0,04081633 \u0026e_{2}\u0026=0,01477833\\\\ x0_{3}\u0026=1,42857143 \u0026x1_{3}\u0026=1,4137931 \u0026x2_{3}\u0026=1,41421144 \u0026fx0_{3}\u0026=0,04081633 \u0026fx1_{3}\u0026=-0,00118906 \u0026e_{3}\u0026=0,00041834\\\\ x0_{4}\u0026=1,4137931 \u0026x1_{4}\u0026=1,41421144 \u0026x2_{4}\u0026=1,41421356 \u0026fx0_{4}\u0026=-0,00118906 \u0026fx1_{4}\u0026=-0,00000601 \u0026e_{4}\u0026=0,00000212\\\\ x0_{5}\u0026=1,41421144 \u0026x1_{5}\u0026=1,41421356 \u0026x2_{5}\u0026=1,41421356 \u0026fx0_{5}\u0026=-0,00000601 \u0026fx1_{5}\u0026=0,0 \u0026e_{5}\u0026=0,0\\\\ x0_{6}\u0026=1,41421356 \u0026x1_{6}\u0026=1,41421356 \u0026x2_{6}\u0026=1,41421356 \u0026fx0_{6}\u0026=0,0 \u0026fx1_{6}\u0026=0,0 \u0026e_{6}\u0026=0,0\\\\ \\\\ \u0026\u0026\\sqrt{2}\u0026=1,41421356 \\end{align} $$For \\(m=13\\) $$ \\begin{align} x0_{0}\u0026=13,0 \u0026x1_{0}\u0026=12,0 \u0026x2_{0}\u0026=12,0 \u0026fx0_{0}\u0026=156,0 \u0026fx1_{0}\u0026=131,0 \u0026e_{0}\u0026=5,24\\\\ x0_{1}\u0026=12,0 \u0026x1_{1}\u0026=6,76 \u0026x2_{1}\u0026=6,76 \u0026fx0_{1}\u0026=131,0 \u0026fx1_{1}\u0026=32,6976 \u0026e_{1}\u0026=1,74294243\\\\ x0_{2}\u0026=6,76 \u0026x1_{2}\u0026=5,01705757 \u0026x2_{2}\u0026=5,01705757 \u0026fx0_{2}\u0026=32,6976 \u0026fx1_{2}\u0026=12,17086665 \u0026e_{2}\u0026=1,03343867\\\\ x0_{3}\u0026=5,01705757 \u0026x1_{3}\u0026=3,9836189 \u0026x2_{3}\u0026=3,9836189 \u0026fx0_{3}\u0026=12,17086665 \u0026fx1_{3}\u0026=2,86921957 \u0026e_{3}\u0026=0,31877821\\\\ x0_{4}\u0026=3,9836189 \u0026x1_{4}\u0026=3,66484069 \u0026x2_{4}\u0026=3,66484069 \u0026fx0_{4}\u0026=2,86921957 \u0026fx1_{4}\u0026=0,43105728 \u0026e_{4}\u0026=0,05635871\\\\ x0_{5}\u0026=3,66484069 \u0026x1_{5}\u0026=3,60848198 \u0026x2_{5}\u0026=3,60848198 \u0026fx0_{5}\u0026=0,43105728 \u0026fx1_{5}\u0026=0,02114223 \u0026e_{5}\u0026=0,00290682\\\\ x0_{6}\u0026=3,60848198 \u0026x1_{6}\u0026=3,60557517 \u0026x2_{6}\u0026=3,60557517 \u0026fx0_{6}\u0026=0,02114223 \u0026fx1_{6}\u0026=0,00017227 \u0026e_{6}\u0026=0,00002388\\\\ x0_{7}\u0026=3,60557517 \u0026x1_{7}\u0026=3,60555129 \u0026x2_{7}\u0026=3,60555129 \u0026fx0_{7}\u0026=0,00017227 \u0026fx1_{7}\u0026=0,00000007 \u0026e_{7}\u0026=0,00000001\\\\ x0_{8}\u0026=3,60555129 \u0026x1_{8}\u0026=3,60555128 \u0026x2_{8}\u0026=3,60555128 \u0026fx0_{8}\u0026=0,00000007 \u0026fx1_{8}\u0026=0,0 \u0026e_{8}\u0026=0,0\\\\ x0_{9}\u0026=3,60555128 \u0026x1_{9}\u0026=3,60555128 \u0026x2_{9}\u0026=3,60555128 \u0026fx0_{9}\u0026=0,0 \u0026fx1_{9}\u0026=0,0 \u0026e_{9}\u0026=0,0\\\\ \\\\ \u0026\u0026\\sqrt{13}\u0026=3,60555128 \\end{align} $$For \\(m=354\\) $$ \\begin{align} x0_{0}\u0026=354,0 \u0026x1_{0}\u0026=353,0 \u0026x2_{0}\u0026=353,0 \u0026fx0_{0}\u0026=124962,0 \u0026fx1_{0}\u0026=124255,0 \u0026e_{0}\u0026=175,74964639\\\\ x0_{1}\u0026=353,0 \u0026x1_{1}\u0026=177,25035361 \u0026x2_{1}\u0026=177,25035361 \u0026fx0_{1}\u0026=124255,0 \u0026fx1_{1}\u0026=31063,68785373 \u0026e_{1}\u0026=58,5830592\\\\ x0_{2}\u0026=177,25035361 \u0026x1_{2}\u0026=118,66729441 \u0026x2_{2}\u0026=118,66729441 \u0026fx0_{2}\u0026=31063,68785373 \u0026fx1_{2}\u0026=13727,92676292 \u0026e_{2}\u0026=46,39103769\\\\ x0_{3}\u0026=118,66729441 \u0026x1_{3}\u0026=72,27625672 \u0026x2_{3}\u0026=72,27625672 \u0026fx0_{3}\u0026=13727,92676292 \u0026fx1_{3}\u0026=4869,85728538 \u0026e_{3}\u0026=25,5041726\\\\ x0_{4}\u0026=72,27625672 \u0026x1_{4}\u0026=46,77208412 \u0026x2_{4}\u0026=46,77208412 \u0026fx0_{4}\u0026=4869,85728538 \u0026fx1_{4}\u0026=1833,62785264 \u0026e_{4}\u0026=15,40238058\\\\ x0_{5}\u0026=46,77208412 \u0026x1_{5}\u0026=31,36970354 \u0026x2_{5}\u0026=31,36970354 \u0026fx0_{5}\u0026=1833,62785264 \u0026fx1_{5}\u0026=630,05830017 \u0026e_{5}\u0026=8,06301365\\\\ x0_{6}\u0026=31,36970354 \u0026x1_{6}\u0026=23,30668989 \u0026x2_{6}\u0026=23,30668989 \u0026fx0_{6}\u0026=630,05830017 \u0026fx1_{6}\u0026=189,20179382 \u0026e_{6}\u0026=3,46039272\\\\ x0_{7}\u0026=23,30668989 \u0026x1_{7}\u0026=19,84629717 \u0026x2_{7}\u0026=19,84629717 \u0026fx0_{7}\u0026=189,20179382 \u0026fx1_{7}\u0026=39,8755115 \u0026e_{7}\u0026=0,92404986\\\\ x0_{8}\u0026=19,84629717 \u0026x1_{8}\u0026=18,92224732 \u0026x2_{8}\u0026=18,92224732 \u0026fx0_{8}\u0026=39,8755115 \u0026fx1_{8}\u0026=4,05144353 \u0026e_{8}\u0026=0,10450337\\\\ x0_{9}\u0026=18,92224732 \u0026x1_{9}\u0026=18,81774395 \u0026x2_{9}\u0026=18,81774395 \u0026fx0_{9}\u0026=4,05144353 \u0026fx1_{9}\u0026=0,10748728 \u0026e_{9}\u0026=0,0028481\\\\ x0_{10}\u0026=18,81774395 \u0026x1_{10}\u0026=18,81489585 \u0026x2_{10}\u0026=18,81489585 \u0026fx0_{10}\u0026=0,10748728 \u0026fx1_{10}\u0026=0,00030575 \u0026e_{10}\u0026=0,00000812\\\\ x0_{11}\u0026=18,81489585 \u0026x1_{11}\u0026=18,81488772 \u0026x2_{11}\u0026=18,81488772 \u0026fx0_{11}\u0026=0,00030575 \u0026fx1_{11}\u0026=0,00000002 \u0026e_{11}\u0026=0,0\\\\ x0_{12}\u0026=18,81488772 \u0026x1_{12}\u0026=18,81488772 \u0026x2_{12}\u0026=18,81488772 \u0026fx0_{12}\u0026=0,00000002 \u0026fx1_{12}\u0026=0,0 \u0026e_{12}\u0026=0,0\\\\ \\\\ \u0026\u0026\\sqrt{354}\u0026=18,81488772 \\end{align} $$Code examples The repo with examples for these algorithms is here. I won\u0026rsquo;t dive deep into the code in this article, but feel free to contact me directly if you have any doubts or suggestions, but I want you try to run the code and the benchmarks so we can take a look at the results in the next section.\nFollow these steps:\n# clone the repo git clone https://github.com/padiazg/root-finding-algorithms-examples.git # move into the folder cd root-finding-algorithms-examples/part-2 # run the examples go run main.go bisection.go newton-raphson.go secant.go --show-summary --values 2,13,354 # run the benchmarks go test -bench=. Benchmarks Once you have cloned and run the examples, let\u0026rsquo;s take a look at the results\n$ go run main.go bisection.go newton-raphson.go secant.go --show-summary --values 2,13,354 threshold: 0.0000001 | max-iter: 64 +-------+----------------+--------------------------+------------+ | VALUE | ALGORITHM | RESULT | ITERATIONS | +-------+----------------+--------------------------+------------+ | 2 | Bisection | 1.4142136 | 24 | | +----------------+--------------------------+------------+ | | Newton-Raphson | 1.4142136 | 4 | | +----------------+--------------------------+------------+ | | Secant | 1.4142136 | 5 | +-------+----------------+--------------------------+------------+ | 13 | Bisection | 3.6055514 | 26 | | +----------------+--------------------------+------------+ | | Newton-Raphson | 3.6055513 | 5 | | +----------------+--------------------------+------------+ | | Secant | 3.6055513 | 7 | +-------+----------------+--------------------------+------------+ | 354 | Bisection | 18.8148878 | 31 | | +----------------+--------------------------+------------+ | | Newton-Raphson | 18.8148877 | 8 | | +----------------+--------------------------+------------+ | | Secant | 18.8148877 | 11 | +-------+----------------+--------------------------+------------+ $ go test -bench=. goos: darwin goarch: amd64 pkg: github.com/padiazg/go-aproximation-demo cpu: Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz BenchmarkSqrtBisection2-16 1561058\t733.2 ns/op BenchmarkSqrtBisection16-16 1397647\t859.2 ns/op BenchmarkSqrtBisection32-16 1418907\t849.9 ns/op BenchmarkSqrtBisection79543-16 949737\t1286 ns/op BenchmarkSqrtBisection6632888162-16 632889\t1679 ns/op BenchmarkSqrtNewtonRaphson2-16 80412462\t14.47 ns/op BenchmarkSqrtNewtonRaphson16-16 58465778\t20.13 ns/op BenchmarkSqrtNewtonRaphson32-16 47134106\t24.45 ns/op BenchmarkSqrtNewtonRaphson79543-16 23997736\t48.41 ns/op BenchmarkSqrtNewtonRaphson6632888162-16 11614274\t99.88 ns/op BenchmarkSqrtSecant2-16 39359683\t27.15 ns/op BenchmarkSqrtSecant16-16 28226810\t39.72 ns/op BenchmarkSqrtSecant32-16 25197651\t48.48 ns/op BenchmarkSqrtSecant79543-16 10315800\t113.1 ns/op BenchmarkSqrtSecant6632888162-16 6023776\t196.7 ns/op PASS ok github.com/padiazg/go-aproximation-demo\t21.194s As we predicted in theory, Newton-Raphson outperforms Bisection and Secant, but Secant falls behind it for just small margin.\nHere are some key observations:\nAccuracy: All three algorithms converge to highly accurate approximations of the square root (e.g., \\(\\sqrt{2} \\approx 1.4142136\\)). Small differences in the last decimal place result from algorithm-specific behavior or computational precision. Iterations: Bisection: Requires the most iterations (24 for \\(\\sqrt{2}\\)​, 26 for \\(\\sqrt{13}\\)​, and 31 for \\(\\sqrt{354}\\)​). This is due to its linear convergence rate, which makes it less efficient compared to the other methods. Newton-Raphson: Achieves the same level of accuracy in significantly fewer iterations (4 for \\(\\sqrt{2}\\)​, 5 for \\(\\sqrt{13}\\) ​, and 8 for \\(\\sqrt{354}\\)​) because of its quadratic convergence rate. Secant: Falls between Bisection and Newton -Raphson in terms of iterations (5 for \\(\\sqrt{2}\\)​, 7 for \\(\\sqrt{13}\\)​, and 11 for \\(\\sqrt{354}\\)​), benefiting from superlinear convergence without requiring derivative calculations. Benchmarks Bisection: The computational cost grows moderately with larger values (e.g., 733 ns/op for \\(\\sqrt{2}\\)​ vs. 1679 ns/op for )\\sqrt{6632888162}$). Newton-Raphson: Outperforms both Bisection and Secant, with the lowest execution times across all values (e.g., 14.47 ns/op for \\(\\sqrt{2}\\), 99.88 ns/op for \\(\\sqrt{6632888162}\\)). Secant: Faster than Bisection but slower than Newton-Raphson (e.g., 27.15 ns/op for \\(\\sqrt{2}\\), 196.7 ns/op for \\(\\sqrt{6632888162}\\)). Given this data, which one you should pick depends on the theory we mentioned in the previous article:\nIf you have access to the derivative of function you definitely should pick Newton-Raphson If the derivative is not available, or too hard to get, a good candidate is Secant as it performs very close to Newton-Rapson If none of above is possible, then you fall back to BIsection, shich is safer and has an assured convergence if you can guess correctly the brackets for the function. Conclusion In this article we explored the Bisection, Newton-Raphson, and Secant methods. Each algorithm offers unique advantages:\nBisection ensures convergence but converges linearly, making it a robust yet slower option. Newton-Raphson demonstrates quadratic convergence, achieving results swiftly if a good initial guess is available and the function\u0026rsquo;s derivative is well-behaved. Secant offers a balance between computational cost and convergence rate, requiring no derivative calculation while converging super-linearly. Through the practical example of calculating square roots, we illustrated the strengths and limitations of these methods in numerical problem-solving. As we progress in this series, we will delve into some more specific examples and how they can be used in real world use cases.\nLinks Numerical root-finding algorithms: Foundations, theory, and advanced methods. Part 1 Numerical root-finding algorithms: Bisection, Newton-Raphson and Secant. Part2 Numerical root-finding algorithms: An unconventional approach. Part3 ","permalink":"https://padiazg.github.io/posts/numerical-root-finding-part2/","summary":"\u003cp\u003eContinuing our series on root-finding algorithms, this article delves deeper into the \u003cstrong\u003eBisection\u003c/strong\u003e (linear convergence), \u003cstrong\u003eNewton-Raphson\u003c/strong\u003e (quadratic convergence), and \u003cstrong\u003eSecant\u003c/strong\u003e (super linear convergence) methods. Each of these algorithms has unique strengths, making them suitable for different scenarios. To illustrate their application, we will use the example of calculating the square root of a number—a simple yet insightful problem.\u003c/p\u003e\n\u003cp\u003eUsing an approximation algorithm to calculate a square root might seem excessive, but please bear with me throughout this article. I chose the square root because the function is straightforward, and its derivative is relatively simple to calculate, allowing us to work through the exercises more easily.\u003c/p\u003e","title":"Numerical root-finding algorithms: Bisection, Newton-Raphson and Secant. Part 2"},{"content":"Root-finding is one of the core problems in computational mathematics. Whether you\u0026rsquo;re solving equations, optimizing functions, or modeling real-world phenomena, the need to find the roots of functions is ubiquitous. This article explores the foundations of root-finding algorithms, their mathematical principles, convergence properties, and real-world applications. Additionally, we will dive into advanced techniques, such as the Secant Method and Brent’s Method, which extend and improve upon traditional approaches.\n1. Introduction to Root-Finding Problems In computational mathematics, finding the root of a function \\(f(x)=0\\) is essential across a range of fields, from physics and engineering to economics and computer science. A root is simply a value where the function evaluates to zero, and root-finding algorithms are designed to approximate these values when exact solutions are not easily obtainable.\nRoot-finding problems arise in many contexts:\nSolving Equations: For instance, finding the point where the gravitational force equals zero in physics or determining the intersection points of curves in geometry. Optimization: Algorithms find prices that optimize supply and demand in economics or optimal control points in engineering. Computer Graphics: Root-finding methods are used in rendering techniques like ray tracing, where finding the intersection of a light ray with 3D surfaces is crucial. Root-finding algorithms are powerful tools in computational science, particularly when exact analytical solutions to nonlinear equations are unavailable.\n2. Fundamental Algorithms Comparison 2.1 Bisection Method The Bisection Method is one of the most basic and reliable root-finding algorithms. It is based on the intermediate value theorem, which states that if a continuous function \\(f(x)\\) changes sign over an interval \\([a,b]\\), then there exists at least one root in the interval.\nMathematical Principles The method works by repeatedly bisecting the interval and selecting the subinterval that contains the root. The midpoint of the interval, \\(m = \\frac{a + b}{2}\\)​, is computed, and the sign of \\(f(m)\\) is checked. If \\(f(a) \\cdot f(m) \u003c 0\\), the root lies between \\(a\\) and \\(m\\), and the interval is updated to \\([a, m]\\). If \\(f(m) \\cdot f(b) \u003c 0\\), the root lies between \\(m\\) and \\(b\\), and the interval is updated to \\([m,b]\\).\nConvergence Characteristics The Bisection Method is guaranteed to converge provided the function is continuous on the interval and the initial guesses are correctly chosen. The convergence is linear, meaning each step reduces the interval size by half.\nPros and Cons Pros: Simple to implement, guaranteed convergence if the initial interval is chosen correctly. Cons: Slow convergence, requiring many iterations to achieve a high degree of accuracy. 2.2 Newton-Raphson Method The Newton-Raphson Method is a widely used root-finding technique that offers much faster convergence than the Bisection Method, especially when an initial guess is close to the true root. It uses the concept of linear approximation to refine the root estimate.\nMathematical Derivation The method uses the derivative of the function to find a tangent line at the current approximation. Given an initial guess \\(x_0\\)​, the iterative formula is: $$ x_{n+1} = x_n - \\frac{f(x_n)}{f'(x_n)} $$ This process continues until the difference between successive approximations is smaller than a specified tolerance.\nConvergence Speed Newton-Raphson has quadratic convergence, meaning that the number of correct digits approximately doubles with each iteration when starting from a sufficiently close guess.\nComputational Complexity The method requires calculating both the function and its derivative at each step, making it computationally expensive compared to methods like Bisection.\nPros and Cons Pros: Fast convergence (quadratic), efficient for well-behaved functions with a good initial guess. Cons: Requires the derivative of the function, can fail or diverge if the derivative is zero or the guess is poor. 3. Advanced Root-Finding Algorithms While the Bisection and Newton-Raphson methods are foundational, they have limitations in certain situations, such as poor initial guesses or the inability to compute derivatives. This has led to the development of more advanced algorithms, such as the Secant Method and Brent’s Method.\n3.1 Secant Method The Secant Method is an improvement on the Newton-Raphson method that does not require the derivative of the function. Instead, it approximates the derivative by using two successive points.\nMathematical Principles The Secant Method iteratively refines guesses using the following formula: $$ x_{n+1} = x_n - \\frac{f(x_n) \\cdot (x_n - x_{n-1})}{f(x_n) - f(x_{n-1})} $$ Here, the approximation of the derivative is made using the slope of the secant line through \\((x_n, f(x_n))\\) and \\((x_{n-1}, f(x_{n-1}))\\).\nConvergence Speed The Secant Method exhibits superlinear convergence, meaning it converges faster than the Bisection Method but slower than Newton-Raphson.\nPros and Cons Pros: Does not require the derivative, faster convergence than the Bisection Method. Cons: Can fail if the two initial guesses are too far apart or if the function behaves erratically. 3.2 Brent’s Method Brent’s Method is a hybrid algorithm that combines the strengths of the Bisection, Secant, and inverse quadratic interpolation methods. It dynamically selects the most appropriate strategy based on the situation, ensuring robustness and efficiency.\nMathematical Principles Brent’s Method switches between the following strategies:\nBisection: When the other methods are unreliable. Secant Method: For faster convergence when appropriate. Inverse Quadratic Interpolation: Fits a quadratic to three points and solves for its root. This combination allows the algorithm to reliably find roots even in difficult cases.\nConvergence Speed Brent’s Method generally exhibits superlinear convergence and performs well in a wide range of problems.\nPros and Cons Pros: Extremely robust, combines the best features of multiple methods, guarantees convergence. Cons: More complex to implement than simpler methods like Bisection. 4. Real-World Applications of Root-Finding Methods Root-finding algorithms are crucial in solving real-world computational problems, and the Newton-Raphson Method, with its quadratic convergence, is often the preferred choice when speed and efficiency are required. Its fast convergence makes it highly valuable in many practical applications, particularly where high precision is needed and an initial guess can be reasonably made.\nEngineering and Physics: Solving Nonlinear Equations In fields like engineering and physics, many problems involve solving nonlinear equations to model dynamic systems, equilibrium points, or interactions. For example, in structural engineering, solving for the points at which forces balance within a system often leads to nonlinear equations. Newton-Raphson\u0026rsquo;s rapid convergence makes it ideal for solving such problems where the function is well-behaved, and a good starting guess is available.\nIn contrast, the Bisection Method is sometimes used in situations where the function is not differentiable or its derivative is hard to compute, but its slower linear convergence can make it impractical when speed is important.\nComputer Graphics: Ray Tracing and Geometric Calculations In computer graphics, where accuracy and speed are essential for rendering, the Newton-Raphson Method is commonly employed for root-finding in 3D rendering algorithms like ray tracing. When computing intersections between light rays and surfaces, for example, Newton-Raphson can quickly hone in on the root, providing the intersection point in a minimal number of iterations, especially when the function is smooth and differentiable.\nThough Brent’s Method and the Secant Method can offer reliable solutions in more complex scenarios, when you know the derivative and can make an initial guess, Newton-Raphson will typically outperform them, achieving results in far fewer iterations.\nEconomics: Solving Market Equilibrium Problems In economics, finding market equilibrium involves solving nonlinear equations that represent supply and demand curves. The Newton-Raphson Method is often used here for its speed in iteratively refining the estimate of the equilibrium price and quantity, especially when good initial guesses are available. For example, finding the point where supply equals demand often involves solving nonlinear equations that describe complex economic systems.\nOn the other hand, if the function is difficult to differentiate, or if you\u0026rsquo;re uncertain about the initial guess, the Bisection Method can be a useful fallback, but it is slower, requiring more iterations to arrive at an accurate solution.\n5. Choosing the Right Method: Linear vs. Quadratic Convergence When deciding between the Bisection Method and the Newton-Raphson Method, the key distinction lies in their convergence behavior and the trade-offs between reliability and speed.\nBisection Method: Guaranteed Convergence but Slow The Bisection Method is a reliable, guaranteed converging method. As long as you can identify an interval where the function changes sign (i.e., \\(f(a) \\cdot f(b) \u003c 0\\)), the method will always converge to a root, provided the function is continuous. However, the rate of convergence is linear, meaning that each step only reduces the error by a constant factor, typically halving the interval at each iteration. For a function with a relatively simple form and when you don\u0026rsquo;t have access to the derivative, this method can be quite useful.\nHowever, in scenarios where the precision and speed are paramount (such as real-time computations in engineering, economics, or graphics), Bisection’s slow convergence can become a bottleneck. It requires a larger number of iterations to achieve the same level of accuracy compared to faster methods like Newton-Raphson.\nNewton-Raphson Method: Rapid Convergence for Smooth Functions The Newton-Raphson Method is favored in many applications where faster convergence is required. Its quadratic convergence means that with each iteration, the error is roughly squared (or halved at an exponentially faster rate). This makes it an extremely fast method when the initial guess is close to the true root, as the number of correct digits roughly doubles with each step.\nExample of Speed: If the error after 5 iterations is 0.1, after 6 iterations, the error may drop to 0.01, and after 7 iterations, it could be reduced to 0.0001. This rapid convergence is why Newton-Raphson is preferred for solving equations in fields like engineering, where quick, precise solutions are necessary. However, for the Newton-Raphson Method to work optimally, the function must be smooth and differentiable, and a good initial guess is required. If these conditions are met, the method can vastly outperform slower methods like Bisection.\nCaveat: Newton-Raphson can fail or diverge if the initial guess is too far from the root, or if the derivative is small or zero. This is a limitation compared to Bisection, which guarantees convergence but at a slower pace.\nWhen to Choose Which Method Choose the Bisection Method: When the function is continuous but not differentiable. When you don’t have access to the derivative. When you can find an initial interval where the function changes sign. When guaranteed, albeit slow, convergence is necessary. Choose the Newton-Raphson Method: When you have access to the derivative and a reasonable initial guess. When rapid convergence and efficiency are required. When dealing with smooth, well-behaved functions that allow for reliable derivative computation. Conclusion In this article, we have examined the core principles of root-finding algorithms, focusing on two of the most fundamental methods: the Bisection Method and the Newton-Raphson Method. While the Bisection Method is simple, reliable, and guarantees convergence, its linear convergence makes it slow, especially in cases where speed is critical. On the other hand, the Newton-Raphson Method offers quadratic convergence, allowing it to find roots far more quickly and efficiently, provided the function is smooth and a good initial guess is available.\nIn real-world applications across fields like engineering, computer graphics, and economics, the Newton-Raphson Method is often the preferred choice due to its superior speed and precision. However, the Bisection Method still holds value in scenarios where reliability and guaranteed convergence are more important than speed.\nAs we move forward in this series, we will explore some real world use cases with their corresponding example code.\nLinks Numerical root-finding algorithms: Foundations, theory, and advanced methods. Part 1 Numerical root-finding algorithms: Bisection, Newton-Raphson and Secant. Part2 Numerical root-finding algorithms: An unconventional approach. Part3 ","permalink":"https://padiazg.github.io/posts/numerical-root-finding-part1/","summary":"\u003cp\u003eRoot-finding is one of the core problems in computational mathematics. Whether you\u0026rsquo;re solving equations, optimizing functions, or modeling real-world phenomena, the need to find the roots of functions is ubiquitous. This article explores the foundations of root-finding algorithms, their mathematical principles, convergence properties, and real-world applications. Additionally, we will dive into advanced techniques, such as the Secant Method and Brent’s Method, which extend and improve upon traditional approaches.\u003c/p\u003e\n\u003chr\u003e\n\u003ch3 id=\"1-introduction-to-root-finding-problems\"\u003e1. Introduction to Root-Finding Problems\u003c/h3\u003e\n\u003cp\u003eIn computational mathematics, finding the root of a function \\(f(x)=0\\) is essential across a range of fields, from physics and engineering to economics and computer science. A root is simply a value where the function evaluates to zero, and root-finding algorithms are designed to approximate these values when exact solutions are not easily obtainable.\u003c/p\u003e","title":"Numerical root-finding algorithms: Foundations, theory, and advanced methods. Part 1"},{"content":"Also published at dev.to\nIntroduction Preparing for the Certified Kubernetes Application Developer (CKAD) certification requires a reliable environment for hands-on practice. While cloud providers are often recommended, setting up a local environment can be more cost-effective and provide valuable learning opportunities. In this guide, I\u0026rsquo;ll walk you through creating a robust local Kubernetes environment using Ubuntu\u0026rsquo;s Multipass and bridge networking.\nWhy Local Setup? When I started preparing for my CKAD certification, I wanted an environment that would:\nProvide consistent networking between nodes Allow full control over the infrastructure Minimize costs compared to cloud solutions Offer flexibility for experimentation Hardware Requirements Before getting started, ensure your system meets these minimum requirements:\nMinimum Requirements:\nCPU: 4 cores (8 threads recommended) RAM: 16GB minimum, 32GB recommended Storage: 100GB free space (SSD recommended) My Test Environment:\nCPU: AMD Ryzen 5 3600 (6 cores, 12 threads) RAM: 64GB DDR4 Storage: 1TB SSD + 1TB HDD + 750GB HDD Note: While you can run this setup on lower specifications, you might experience performance issues when running multiple containers and services.\nSystem Compatibility This guide has been tested on:\nUbuntu 24.10 (host system) Ubuntu 22.04 LTS (Jammy) for VMs Multipass 1.14.1 LXD 5.21.2 LTS While the steps should work on other Ubuntu versions (20.04+), you might encounter slight differences in network interface names or default configurations. If you\u0026rsquo;re using Ubuntu 22.04 or earlier, you may need to modify the networkd configuration syntax slightly.\nNetwork Architecture Before we dive into the setup, let\u0026rsquo;s understand the network architecture we\u0026rsquo;ll be creating:\nOur setup creates multiple network interfaces:\nBridge Network (br0): Primary network for Kubernetes communication Host Network (enp37s0): Connection to external network VM Networks: Each VM gets two interfaces enp5s0: Multipass default network enp6s0: Bridge network interface Setting Up the Network Bridge Our first task is creating a dedicated network bridge for our Kubernetes nodes. We\u0026rsquo;ll use systemd-networkd for this purpose, which provides a robust and modern networking stack.\n1. Preparing the Network Environment First, we need to disable NetworkManager and enable systemd-networkd:\n# Disable NetworkManager sudo systemctl stop NetworkManager sudo systemctl disable NetworkManager # Enable systemd-networkd sudo systemctl enable systemd-networkd sudo systemctl start systemd-networkd # Configure DNS resolution sudo systemctl enable systemd-resolved sudo systemctl start systemd-resolved sudo rm /etc/resolv.conf sudo ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf 2. Configuring the Bridge We\u0026rsquo;ll create a bridge network with the following specifications:\nNetwork: 172.19.180.0/24 Gateway: 172.19.180.254 DHCP Range: 172.19.180.1 - 172.19.180.253 Create two configuration files in /etc/systemd/network:\nBridge device definition (50-br0.netdev):\n[NetDev] Name=br0 Kind=bridge Bridge network configuration (51-br0-bind.network):\n[Match] Name=br0 [Network] Address=172.19.180.254/24 IPForward=yes ConfigureWithoutCarrier=yes DHCPServer=yes [DHCPServer] PoolSize=253 EmitRouter=yes EmitDNS=yes DNS=8.8.8.8 DefaultLeaseTimeSec=600 MaxLeaseTimeSec=7200 [DHCPServerStaticLease] MACAddress=52:54:00:ab:cd:01 Address=172.19.180.1 [DHCPServerStaticLease] MACAddress=52:54:00:ab:cd:02 Address=172.19.180.2 3. Enabling IP Forwarding To allow communication between nodes and the internet:\n# enable IP forwarding in the kernel $ sysctl -w net.ipv4.ip_forward=1 $ sysctl -w net.ipv6.conf.default.forwarding=1 # check $ sysctl net.ipv4.ip_forward net.ipv4.ip_forward = 1 $ sysctl net.ipv6.conf.default.forwarding net.ipv6.conf.default.forwarding = 1 Set forwarding rule for iptables\n# Configure iptables to allow forwarding sudo iptables -P FORWARD ACCEPT # allow nat forwarding to our bridge sudo iptables -t nat -A POSTROUTING -o \u0026lt;host-nic\u0026gt; -j MASQUERADE Optional: Make it permanent Ubuntu comes with ufw installed by default but it adds lots of restrictions and issues with Multipass regarding DHCP and traffic forwarding so we are going to use plain iptables to manage the firewall rules and make it persistent.\nDisclaimer: Follow this steps only if you are sure and did your research about how it will affect your system as they will change the firewall manager for your host. Take this as a suggestion if it works for you.\n# to persist the rules after restarts, it will uninstall ufw in the process and save the existing rules $ sudo apt-get install iptables-persistent # set default FOrWARD policy to ACCEPT $ sudo iptables -P FORWARD ACCEPT # allow nat forwarding for our brigde network. change enp37s0 with your host interface $ sudo iptables -t nat -A POSTROUTING -o enp37s0 -j MASQUERADE # save the rules $ sudo netfilter-persistent save # check rules $ sudo iptables -L $ sudo iptables -t nat -L Creating Virtual Machines with Multipass Multipass provides a lightweight way to create Ubuntu VMs. We\u0026rsquo;ll configure it to work with our bridge network.\n1. Setting Up Multipass with LXD snap install lxd snap connect multipass:lxd lxd multipass set local.driver=lxd 2. Launching Kubernetes Nodes # Control plane node multipass launch jammy \\ --name ckad-cp \\ --cpus 2 \\ --memory 8G \\ --disk 20G \\ --network name=br0,mode=auto,mac=52:54:00:ab:cd:01 # Worker node multipass launch jammy \\ --name ckad-wn0 \\ --cpus 2 \\ --memory 8G \\ --disk 20G \\ --network name=br0,mode=auto,mac=52:54:00:ab:cd:02 3. Optimizing Network Configuration To ensure Kubernetes uses the correct network interface, we need to adjust the interface priorities on each node. Here\u0026rsquo;s a quick way to do it using yq:\n# Install yq sudo wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/bin/yq \\ \u0026amp;\u0026amp; sudo chmod +x /usr/bin/yq # Update netplan configuration sudo cp /etc/netplan/50-cloud-init.yaml /etc/netplan/50-cloud-init.yaml.old sudo yq \u0026#39;.network.ethernets.default.match.macaddress as $default | .network.ethernets.extra0.match.macaddress as $extra | .network.ethernets.default.match.macaddress = $extra | .network.ethernets.extra0.match.macaddress = $default\u0026#39; \\ /etc/netplan/50-cloud-init.yaml.old | sudo tee /etc/netplan/50-cloud-init.yaml # Restart the node sudo reboot Troubleshooting Guide Common Issues and Solutions Bridge Network Not Coming Up\n# Check bridge status ip link show br0 # If DOWN, try: sudo ip link set br0 up VMs Can\u0026rsquo;t Reach Internet\nVerify IP forwarding: sysctl net.ipv4.ip_forward Check iptables rules: sudo iptables -L -v -n Verify DNS resolution: dig @8.8.8.8 google.com DHCP Not Working on Bridge\nCheck systemd-networkd logs: journalctl -u systemd-networkd Verify bridge configuration: networkctl status br0 VM Network Priority Issues\nVerify interface metrics: ip route show Check netplan configuration: cat /etc/netplan/50-cloud-init.yaml Verification Steps After setup, verify your environment:\nNetwork Connectivity\n# From VMs ping 172.19.180.254 # Should reach bridge ping 8.8.8.8 # Should reach internet Interface Priority\n# Should show bridge interface as priority ip route | grep default DNS Resolution\n# Should resolve correctly nslookup kubernetes.io Performance Optimization Tips VM Resource Allocation\nDon\u0026rsquo;t overcommit CPU cores Leave at least 4GB RAM for host system Use SSD for VM storage when possible Network Performance\nEnable jumbo frames if your network supports it: sudo ip link set br0 mtu 9000 Adjust network buffer sizes: sudo sysctl -w net.core.rmem_max=16777216 sudo sysctl -w net.core.wmem_max=16777216 Conclusion With this setup, you now have a robust local environment for CKAD preparation. The bridge network configuration ensures reliable communication between nodes, while Multipass provides easy VM management. This environment strikes a balance between functionality and resource efficiency, making it perfect for learning Kubernetes administration.\nRemember to monitor system resources during heavy testing, and consider adjusting VM resources based on your workload requirements. While this setup requires more initial configuration than cloud-based alternatives, it provides valuable hands-on experience with networking and system administration concepts that will serve you well in your Kubernetes journey.\nNext steps would be to install Kubernetes components and configure your cluster following the provided documentation by the course.\nHappy practicing!\nAdditional Resources Multipass Documentation systemd-networkd Documentation CKAD Curriculum Kubernetes Documentation ","permalink":"https://padiazg.github.io/posts/k8s-cluster-with-multipass/","summary":"\u003cp\u003eAlso published at \u003ca href=\"https://dev.to/padiazg/setting-up-a-local-kubernetes-environment-with-multipass-and-bridge-networking-4cpa\"\u003edev.to\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"introduction\"\u003eIntroduction\u003c/h2\u003e\n\u003cp\u003ePreparing for the Certified Kubernetes Application Developer (CKAD) certification requires a reliable environment for hands-on practice. While cloud providers are often recommended, setting up a local environment can be more cost-effective and provide valuable learning opportunities. In this guide, I\u0026rsquo;ll walk you through creating a robust local Kubernetes environment using Ubuntu\u0026rsquo;s Multipass and bridge networking.\u003c/p\u003e\n\u003ch2 id=\"why-local-setup\"\u003eWhy Local Setup?\u003c/h2\u003e\n\u003cp\u003eWhen I started preparing for my CKAD certification, I wanted an environment that would:\u003c/p\u003e","title":"Setting up a local Kubernetes environment with Multipass and bridge networking"},{"content":"Also published at dev.to\nIntroduction Obsidian has become a powerful tool for note-taking and personal knowledge management, but one question often comes up: \u0026ldquo;How can I sync my notes across devices?\u0026rdquo; While Obsidian offers a paid sync service, there\u0026rsquo;s a robust alternative using GitHub that\u0026rsquo;s both free and secure. In this guide, I\u0026rsquo;ll walk you through setting up GitHub synchronization for your Obsidian vault, whether you\u0026rsquo;re on desktop or mobile.\nPrerequisites Before we begin, you\u0026rsquo;ll need:\nAn Obsidian installation A GitHub account Basic familiarity with Git concepts (though I\u0026rsquo;ll explain the essential commands) Setting Up Your GitHub Repository Create a private GitHub repository to store your notes Generate a personal access token: Navigate to GitHub Settings → Developer Settings → Personal access tokens → Fine-grained tokens Set the following permissions: Read access to metadata Read and Write access to code and commit statuses Pro Tip: While classic tokens work too, fine-grained tokens offer better security through more precise permission control.\nCreating Your Obsidian Vault To ensure a smooth setup, we\u0026rsquo;ll start fresh:\nCreate a new vault in Obsidian Choose your preferred name and location Remove any default files (like Welcome.md) Installing and Configuring the Git Plugin Enable community plugins in Obsidian: Go to Vault\u0026rsquo;s setup → Community plugins Toggle \u0026ldquo;Turn on community plugins\u0026rdquo; Install the Git plugin by Vinzent: Navigate to Browse → search for \u0026ldquo;Git\u0026rdquo; Install and enable the plugin Don\u0026rsquo;t worry if you see a message about not finding a valid Git repository—that\u0026rsquo;s expected at this stage.\nRepository Setup Methods Mobile Setup Mobile devices use a JavaScript implementation of Git called isomorphic-git, making the setup process slightly different:\nIn Git plugin settings, scroll to Authentication/commit author Enter your GitHub username Paste your personal access token Use the command palette to find \u0026ldquo;git clone an existing remote repo\u0026rdquo; Enter your repository\u0026rsquo;s HTTPS URL Select \u0026ldquo;Vault Root\u0026rdquo; as the clone directory Choose \u0026ldquo;NO\u0026rdquo; when asked about existing .obsidian directory Desktop Setup For desktop users, you can use terminal commands for a more traditional Git setup:\ncd your/vault/folder rm * git init git branch -m master git remote add origin https://\u0026lt;your-personal-token\u0026gt;@github.com/username/repo.git git pull origin master Important: Managing .gitignore To prevent synchronization conflicts, create a .gitignore file with these entries:\n.obsidian .trash .vscode conflict-files-obsidian-git.md On mobile, use the \u0026ldquo;git edit .gitignore\u0026rdquo; command from the palette to add these entries.\nDaily Synchronization Workflow Once everything is set up, syncing becomes straightforward:\nOpen Git source control (via UI or command palette) Stage changed files using the + icon Commit changes with the check icon Push changes using the upload icon Pull updates using the download icon For convenience, there\u0026rsquo;s a \u0026ldquo;Commit-and-sync\u0026rdquo; button that combines staging, committing, and syncing into one action.\nConclusion Setting up GitHub synchronization for Obsidian might seem daunting at first, but it offers a powerful and free way to keep your notes in sync across devices. This setup not only provides version control for your notes but also gives you complete control over your data. With the workflow established here, you can focus on what matters most: capturing and developing your ideas in Obsidian while maintaining a reliable backup of your knowledge base. Remember to regularly sync your changes and keep your access token secure. Happy note-taking!\n","permalink":"https://padiazg.github.io/posts/sync-obsidian-with-github/","summary":"\u003cp\u003eAlso published at \u003ca href=\"https://dev.to/padiazg/how-to-sync-your-obsidian-vault-using-github-a-complete-guide-2l08\"\u003edev.to\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"introduction\"\u003eIntroduction\u003c/h2\u003e\n\u003cp\u003eObsidian has become a powerful tool for note-taking and personal knowledge management, but one question often comes up: \u0026ldquo;How can I sync my notes across devices?\u0026rdquo; While Obsidian offers a paid sync service, there\u0026rsquo;s a robust alternative using GitHub that\u0026rsquo;s both free and secure. In this guide, I\u0026rsquo;ll walk you through setting up GitHub synchronization for your Obsidian vault, whether you\u0026rsquo;re on desktop or mobile.\u003c/p\u003e\n\u003ch2 id=\"prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cp\u003eBefore we begin, you\u0026rsquo;ll need:\u003c/p\u003e","title":"How to sync your Obsidian vault using GitHub: A complete guide"},{"content":"Also published at dev.to\nEver embarked on a project that seemed straightforward at first, only to find yourself tumbling down a rabbit hole of challenges and discoveries? That\u0026rsquo;s exactly what happened when I decided to breathe new life into my ageing Kubernetes cluster. What began as a simple upgrade turned into an odyssey through the world of single-board computers, operating systems, and DIY ingenuity. It all started a few years ago with a Raspberry Pi 2, four Raspberry Pi Zeros, and a cluster hat from 8086.net. Little did I know that this modest setup would lead me on a journey spanning multiple hardware platforms, wrestling with ARM architectures, and ultimately crafting my own solutions to keep my cluster alive and kicking. In this post, I\u0026rsquo;ll take you through the twists and turns of my cluster resurrection project. From the initial roadblocks of discontinued support to the thrill of discovering alternative hardware, and finally, to the satisfaction of creating custom solutions. Whether you\u0026rsquo;re a fellow tinkerer, a Kubernetes enthusiast, or simply curious about the world of single-board computing, buckle up – this tale of perseverance and problem-solving might just inspire your next tech adventure.\nA bit of history The Initial Setup It all began a few years ago when I stumbled upon the cluster hats from 8086.net. Intrigued by the possibility of creating my own Kubernetes cluster, I decided to take the plunge. That old Raspberry Pi 2 Model B that had been gathering dust in a drawer finally would have a purpose! For the cluster nodes, there\u0026rsquo;s nothing to think about, just got some Raspberry Pi Zeros. Little did I know that acquiring these tiny powerhouses would be my first hurdle. Due to their popularity and supply constraints, most suppliers had implemented a strict one-per-customer limit. Undeterred, I embarked on a quest that led me to four different suppliers just to obtain the necessary quartet of Zeros.\nWith all the hardware in hand, I assembled my cluster. The Raspberry Pi 2 served as the controller, while the four Zeros, neatly arranged on the cluster hats, formed the nodes. I opted for K3s, a lightweight Kubernetes distribution perfect for my modest hardware. For a while, everything hummed along smoothly. My little cluster was up and running, handling tasks and teaching me the ins and outs of Kubernetes management.\nThe Fall of 32-bit and the Quest for Alternatives The bliss was short-lived. As technology marched forward, K8s and K3s made the decision to drop support for ARM 32-bit architectures. Suddenly, my trusty Raspberry Pi Zeros were obsolete for this purpose. I found myself at a crossroads – should I abandon the project or find a way to adapt? My first instinct was to look at the Raspberry Pi Zero 2 W, a 64-bit capable successor. However, I quickly ran into familiar problems: high prices and purchase limits. It was déjà vu all over again.\nEnter the Banana Pi In my search for alternatives, I stumbled upon the Banana Pi M2 Zero. These boards were not only drop-in replacements with the same form factor and pinout as the Pi Zeros, but they also sported 64-bit processors. Best of all, they were significantly cheaper and had no quantity limitations.\nThanks to a helpful thread on the Cluster Hat\u0026rsquo;s Google Groups page, I found pre-built images and enough information to get the Banana Pis up and running as nodes. My cluster was back in business, now with 64-bit capable nodes.\nThe Final Evolution: Orange Pi CM4 Recently, I decided it was time for the controller board to join the 64-bit party. In the spirit of exploration (and, admittedly, for the fun of it), I opted for an Orange Pi CM4 with a base board to replace the ageing Raspberry Pi 2. The form factor and pinout matched, making it a perfect candidate. However, this final upgrade proved to be the most challenging. There were no pre-built images for using the Orange Pi as a controller with the cluster hat. I found myself diving deep into the differences between Raspbian/Raspberry Pi OS and the various operating systems available for the Orange Pi.\nThe Home Stretch: Custom Solutions Over the next couple of weeks, I immersed myself in learning the intricacies of operating systems for Orange Pi and Banana Pi. I spent countless hours refactoring and updating the original scripts provided by Cluster Hat. It was a journey of discovery, frustration, and ultimately, triumph. The result of this labor was the creation of two GitHub repositories containing scripts to smoothly create images for both the Orange Pi CM4 controller and the Banana Pi M2 Zero nodes. What started as a simple cluster project had evolved into a deep dive into single-board computing, operating systems, and custom software solutions.\nHands on! Controller board The main components used on the controller board:\nOrange Pi CM4 4G32G+CM4 Base Board: RK3566 CPU, 4G DDR4 RAM, 32G eMMC on-board storage A 128G 2242 M.2 NVME PCIe 3.0x4 SSD card (optional, I plan to use it for PVC provisioning on Kubernetes) 3.5mm pitch screw terminal. For independently powering the hat, see [here](3.5mm pitch screw terminal) Get the images From the repo Download the images from the releases page on the repo and skip to the Burn it section below\nBuild them yourself You might want to fine-tune or customize the images.\n# clone the repo $ git clone git@github.com:padiazg/clusterhat-orangepi-cm4.git $ cd clusterhat-orangepi-cm4 # create the required folders $ mkdir -p build/dest build/img build/mnt Download a base image from here into the build/img folder, I use the Ubuntu Jammy server image as it was the most updated and flawless from the options available.\nI don\u0026rsquo;t provide a shell example for it as there\u0026rsquo;s no way, I think, to download a Google Drive file straightforwardly with wget or curl\nTime to create the images\n$ cd build # you need sudo because of losetup and mount used in the scripts $ sudo ./create.sh Orangepicm4_1.0.6 # once the script has finished the images should be in build/dest $ ls -l dest Burn it Burn the image into an SD card by using any method you\u0026rsquo;re comfortable with: Raspberry Pi Imager, Balena Etcher, dd\n# list the block storages to find your SD $ lsblk AME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS sda 8:0 0 698,6G 0 disk └─sda1 8:1 0 698,6G 0 part /home/pato/vaults/backup sdb 8:16 0 931,5G 0 disk └─sdb1 8:17 0 931,5G 0 part /home/pato/vaults/mis-cosas sdc 8:32 1 29,7G 0 disk └─sdc1 8:33 1 29,4G 0 part zram0 251:0 0 16G 0 disk [SWAP] nvme0n1 259:0 0 931,5G 0 disk ├─nvme0n1p1 259:1 0 1022M 0 part /boot/efi ├─nvme0n1p2 259:2 0 4G 0 part /recovery ├─nvme0n1p3 259:3 0 922,5G 0 part / └─nvme0n1p4 259:4 0 4G 0 part └─cryptswap 252:0 0 4G 0 crypt [SWAP] # the SD is at /dev/sdc in this example $ sudo umount /dev/sdc $ sudo dd bs=1M if=build/dest/Orangepicm4_1.0.6-1-ubuntu_jammy_server_linux5.10.160-ClusterCTRL-CNAT.img of=/dev/sdc status=progress Boot and access the controller Place the SD card into the board and power it. Find out what\u0026rsquo;s the IP address assigned to the board, there are many ways but here\u0026rsquo;s one:\n$ sudo nmap -sS 192.168.1.0/24 ... Nmap scan report for pi.hole (192.168.1.100) Host is up (0.00018s latency). Not shown: 994 closed ports PORT STATE SERVICE 22/tcp open ssh 53/tcp open domain 80/tcp open http 81/tcp open hosts2-ns 443/tcp open https 8443/tcp open https-alt MAC Address: DC:A6:32:BB:97:30 (Raspberry Pi Trading) Nmap scan report for clusterhat-01.local.patodiaz.io (192.168.1.110) Host is up (0.00045s latency). Not shown: 995 closed ports PORT STATE SERVICE 22/tcp open ssh 111/tcp open rpcbind 2049/tcp open nfs 5555/tcp open freeciv 8000/tcp open http-alt MAC Address: 00:00:A4:ED:A7:29 (Acorn Computers Limited) Nmap scan report for cnat.local (192.168.1.235) Host is up (0.00056s latency). Not shown: 995 closed ports PORT STATE SERVICE 22/tcp open ssh 111/tcp open rpcbind 2049/tcp open nfs 5555/tcp open freeciv 49175/tcp open unknown MAC Address: 00:00:A4:FD:FF:FD (Acorn Computers Limited) ... I leverage Pi-hole\u0026rsquo;s DHCP capabilities to implement MAC address-based static IP assignment for key devices within my local network. This approach allows for consistent addressing of critical nodes. Furthermore, I utilize Pi-hole\u0026rsquo;s local DNS functionality to pair each of these static IP addresses with a corresponding domain name, facilitating easier identification and access to these devices across the network.\nYou should be able to access the controller now. The default username and password is \u0026ldquo;pi:clusterctrl\u0026rdquo;\n$ ssh pi@192.168.1.213 Boot from eMMC You might also want to use the eMMC storage, so you don\u0026rsquo;t need a SD card to boot. In such a case, you still need the SD to boot the board and copy the OS to the eMMC. This procedure is described in the manual found here\nCreate a bootable SD. Use any base image, or those you created or downloaded from the repo, as long as it can boot the board. Copy the image to the SD\n# mount the SD card to copy the image $ mount /dev/sdc /mnt/p2 $ cp dest/Orangepicm4_1.0.6-1-ubuntu_jammy_server_linux5.10.160-ClusterCTRL-CNAT.img /mnt/p2/home/your_user Boot the board with the SD, then copy the image to the eMMC\n# identify the eMMC device $ ls /dev/mmcblk*boot0 | cut -c1-12** /dev/mmcblk0 # clear the device, use the device from the prior step $ sudo dd bs=1M if=/dev/zero of=/dev/mmcblk0 count=5000 status=progress # copy the image $ sudo dd bs=1M \\ if=Orangepicm4_1.0.6-1-ubuntu_jammy_server_linux5.10.160-ClusterCTRL-CNAT.img \\ of=/dev/mmcblk0 \\ status=progress # reboot $ sync \u0026amp;\u0026amp; reboot Unplug the SD to allow the board to boot from the eMMC.\nThe nodes As nodes, I\u0026rsquo;m using four Banana Pi M2 Zero. The reasons are that they are cheap, the CPU has four 64-bit cores, and there\u0026rsquo;s no restriction on how many I can buy at once, amongst other improvements you can check on their wiki The instructions for creating the images are pretty much the same as those for the controller, so I\u0026rsquo;ll try not to make it longer.\nGet the images From the repo Download the images from the releases page on the repo and skip to the Burn it section below\nBuild them yourself # clone the repo $ git clone git@github.com:padiazg/clusterhat-orangepi-cm4.git $ cd clusterhat-orangepi-cm4 # create the required folders $ mkdir -p build/dest build/img build/mnt To get a base image for the BPi M2 Zero that works well with the cluster hat is a bit trickier, mostly because of kernel support for usb-otg which is fundamental for the nodes. Download the Debian Bullseye base image from here into the build/img folder, here\u0026rsquo;s a direct link. This one works as expected, and is the most updated I could successfully make it work.\nI use a custom setting to create images prepared to work with a CNAT controller because it is what I use in my infra. I\u0026rsquo;ll explain later the differences between using a CNAT and a CBRIDGE controller.\nI create a config-local.sh file next to the config.sh file\n#!/bin/sh UPGRADE=1 GROWLITE=\u0026#34;2G\u0026#34; CNAT_IMAGES=1 Now create the images\n$ cd build $ sudo ./create.sh Armbian_22.08.0 # the images should be in build/dest $ ls -l dest Burn it # list the block storages to find your SD $ lsblk # SD is at /dev/sdc for this example $ sudo umount /dev/sdc $ sudo dd bs=1M if=build/dest/Armbian_22.08.0-1-trunk_Bananapim2zero_bullseye_current_5.15.43-ClusterCTRL-p1-CNAT.img of=/dev/sdc status=progress Boot and access the node Place the SD card into the node. To start the node we need to use the clusterctrl tool. Please read the cluster-hat control page to get familiarized with the basic tasks\nAt the controller\n# get some info about the cluster-hat $ clusterctrl status # start the P1 node $ clusterctrl on p1 # stop the P1 node $ clusterctrl off p1 Let\u0026rsquo;s explain a bit the networking\n## the network interfaces $ ip link 1: lo: \u0026lt;LOOPBACK,UP,LOWER_UP\u0026gt; mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: eth0: \u0026lt;BROADCAST,MULTICAST,UP,LOWER_UP\u0026gt; mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000 link/ether 00:00:a4:ed:a7:29 brd ff:ff:ff:ff:ff:ff 6: wlan0: \u0026lt;BROADCAST,MULTICAST\u0026gt; mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 54:78:c9:0d:8c:34 brd ff:ff:ff:ff:ff:ff 7: brint: \u0026lt;NO-CARRIER,BROADCAST,MULTICAST,UP\u0026gt; mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000 link/ether ce:90:04:cf:0c:74 brd ff:ff:ff:ff:ff:ff 11: br0: \u0026lt;BROADCAST,MULTICAST,UP,LOWER_UP\u0026gt; mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 link/ether 00:00:a4:ed:a7:29 brd ff:ff:ff:ff:ff:ff 39: ethpi2: \u0026lt;BROADCAST,MULTICAST,UP,LOWER_UP\u0026gt; mtu 1500 qdisc fq_codel master br0 state UNKNOWN mode DEFAULT group default qlen 1000 link/ether 00:22:82:ff:fe:02 brd ff:ff:ff:ff:ff:ff 41: ethpi3: \u0026lt;BROADCAST,MULTICAST,UP,LOWER_UP\u0026gt; mtu 1500 qdisc fq_codel master br0 state UNKNOWN mode DEFAULT group default qlen 1000 link/ether 00:22:82:ff:fe:03 brd ff:ff:ff:ff:ff:ff 42: ethpi4: \u0026lt;BROADCAST,MULTICAST,UP,LOWER_UP\u0026gt; mtu 1500 qdisc fq_codel master br0 state UNKNOWN mode DEFAULT group default qlen 1000 link/ether 00:22:82:ff:fe:04 brd ff:ff:ff:ff:ff:ff ... # the addresses assigned to each one $ ip a 1: lo: \u0026lt;LOOPBACK,UP,LOWER_UP\u0026gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: \u0026lt;BROADCAST,MULTICAST,UP,LOWER_UP\u0026gt; mtu 1500 qdisc mq state UP group default qlen 1000 link/ether 00:00:a4:ed:a7:29 brd ff:ff:ff:ff:ff:ff inet 192.168.1.110/24 brd 192.168.1.255 scope global dynamic eth0 valid_lft 80240sec preferred_lft 80240sec inet6 fe80::200:a4ff:feed:a729/64 scope link valid_lft forever preferred_lft forever 3: brint: \u0026lt;NO-CARRIER,BROADCAST,MULTICAST,UP\u0026gt; mtu 1500 qdisc noqueue state DOWN group default qlen 1000 link/ether ce:90:04:cf:0c:74 brd ff:ff:ff:ff:ff:ff inet 172.19.180.254/24 brd 172.19.180.255 scope global brint valid_lft forever preferred_lft forever 4: br0: \u0026lt;BROADCAST,MULTICAST,UP,LOWER_UP\u0026gt; mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 00:00:a4:ed:a7:29 brd ff:ff:ff:ff:ff:ff inet 172.19.181.254/24 brd 172.19.181.255 scope global br0 valid_lft forever preferred_lft forever inet6 fe80::200:a4ff:feed:a729/64 scope link valid_lft forever preferred_lft forever 5: ethpi1: \u0026lt;BROADCAST,MULTICAST,UP,LOWER_UP\u0026gt; mtu 1500 qdisc fq_codel master br0 state UNKNOWN group default qlen 1000 link/ether 00:22:82:ff:fe:01 brd ff:ff:ff:ff:ff:ff inet6 fe80::222:82ff:feff:fe01/64 scope link valid_lft forever preferred_lft forever 6: ethpi2: \u0026lt;BROADCAST,MULTICAST,UP,LOWER_UP\u0026gt; mtu 1500 qdisc fq_codel master br0 state UNKNOWN group default qlen 1000 link/ether 00:22:82:ff:fe:02 brd ff:ff:ff:ff:ff:ff inet6 fe80::222:82ff:feff:fe02/64 scope link valid_lft forever preferred_lft forever 7: ethpi3: \u0026lt;BROADCAST,MULTICAST,UP,LOWER_UP\u0026gt; mtu 1500 qdisc fq_codel master br0 state UNKNOWN group default qlen 1000 link/ether 00:22:82:ff:fe:03 brd ff:ff:ff:ff:ff:ff inet6 fe80::222:82ff:feff:fe03/64 scope link valid_lft forever preferred_lft forever 8: ethpi4: \u0026lt;BROADCAST,MULTICAST,UP,LOWER_UP\u0026gt; mtu 1500 qdisc fq_codel master br0 state UNKNOWN group default qlen 1000 link/ether 00:22:82:ff:fe:04 brd ff:ff:ff:ff:ff:ff inet6 fe80::222:82ff:feff:fe04/64 scope link valid_lft forever preferred_lft forever ... The ethpix interfaces are added to the br0 bridge, they share the 171.19.181.0/24 network:\n# the controller $ ping 172.19.181.254 # the P1 node $ ping 172.19.181.1 # the P2 node $ ping 172.19.181.2 # the P3 node $ ping 172.19.181.3 # the P4 node $ ping 172.19.181.4 Worth mentioning that the mac-addresses of each node follow the pattern 00:22:82:ff:fe:0x where x is a number between 1 and 4 matching the node number. This is very useful when assigning IP addresses based on the mac-addresses, especially if we are in a CBRIDGE configuration.\nYou should be able to ssh any of the nodes using the info above\n$ ssh pi@172.19.181.1 # P1 $ ssh pi@172.19.181.2 # P2 # and so on Difference between CBRIDGE and CNAT The main difference between the two is how nodes get an IP address, and how the cluster components access the network. At both configurations the br0 network is configured and each node is assigned the internal ip addresses as mentioned before, but the main difference is how the traffic is routed to the rest of the network and other networks like the internet.\nIn a CBRIDGE configuration the nodes get bridged through the controller network and access the network directly. Each node will get an ip address either manually or via an DHCP present in the network, as if it is a device directly connected to the network. In the other hand, in a CNAT configuration, the nodes traffic is nated and the controller acts as a router hiding the nodes from the outside.\nConclusion: Lessons Learned and the Road Ahead As I sit back and reflect on this journey, from those first Raspberry Pi Zeros to the current setup with Banana Pi nodes and an Orange Pi controller, I\u0026rsquo;m struck by how much I\u0026rsquo;ve learned and how far this project has come.\nWhat started as a simple desire to build a Kubernetes cluster became a crash course in hardware compatibility, operating system intricacies, and the importance of community knowledge. Each obstacle - from supply constraints to architecture changes - pushed me to think creatively and expand my skillset.\nPerhaps the most valuable lesson was the reminder that in the world of technology, change is the only constant. The ability to adapt, whether it\u0026rsquo;s finding alternative hardware or writing custom scripts, is crucial. This project also reinforced the power of open-source communities. Without the shared knowledge and pre-built images from other enthusiasts, many of the hurdles would have been much harder to overcome.\nThe two GitHub repositories I\u0026rsquo;ve created for image creation are not just the end result of this project, but also my contribution back to the community that helped me along the way. I hope that other tinkerers and cluster enthusiasts will find them useful in their own journeys.\nLooking ahead, I\u0026rsquo;m excited about the possibilities this upgraded cluster opens up. With more powerful, 64-bit capable nodes and a controller, I can explore more complex Kubernetes deployments and perhaps even venture into edge computing scenarios. By the way, I already have two Orange Pi Zero 2W with 2GB RAM each, even more powerful than the Banana Pi M2 Zero,and also just saw there are some Radxa ZERO 3W with 4G of RAM, both of them bringing new challenges to this project.\nThis project may have started with a handful of Pis and a dream, but it\u0026rsquo;s grown into so much more. It\u0026rsquo;s a testament to the joy of problem-solving, the power of perseverance, and the endless possibilities when you\u0026rsquo;re willing to think outside the (Raspberry Pi) box.\nSo, what\u0026rsquo;s next? Who knows - but I\u0026rsquo;m certain it will involve more tinkering, learning, and pushing the boundaries of what\u0026rsquo;s possible with these amazing single-board computers. The sky\u0026rsquo;s the limit!\n","permalink":"https://padiazg.github.io/posts/from-pi-to-sky/","summary":"\u003cp\u003eAlso published at \u003ca href=\"https://dev.to/padiazg/from-pi-to-sky-how-my-kubernetes-cluster-evolved-beyond-raspberry-nf2\"\u003edev.to\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eEver embarked on a project that seemed straightforward at first, only to find yourself tumbling down a rabbit hole of challenges and discoveries? That\u0026rsquo;s exactly what happened when I decided to breathe new life into my ageing Kubernetes cluster. What began as a simple upgrade turned into an odyssey through the world of single-board computers, operating systems, and DIY ingenuity.\nIt all started a few years ago with a Raspberry Pi 2, four Raspberry Pi Zeros, and a cluster hat from 8086.net. Little did I know that this modest setup would lead me on a journey spanning multiple hardware platforms, wrestling with ARM architectures, and ultimately crafting my own solutions to keep my cluster alive and kicking.\nIn this post, I\u0026rsquo;ll take you through the twists and turns of my cluster resurrection project. From the initial roadblocks of discontinued support to the thrill of discovering alternative hardware, and finally, to the satisfaction of creating custom solutions. Whether you\u0026rsquo;re a fellow tinkerer, a Kubernetes enthusiast, or simply curious about the world of single-board computing, buckle up – this tale of perseverance and problem-solving might just inspire your next tech adventure.\u003c/p\u003e","title":"From Pi to Sky: How My Kubernetes Cluster Evolved Beyond Raspberry"}]