# 42_EXT_05_computorv1


## ressources

- project intra : https://projects.intra.42.fr/projects/42cursus-computorv1 
- project luke : https://github.com/LuckyLaszlo/computorv1 

## install

this project uses submodules (maybe recursively), so either : 

- `git clone --recurse-submodules <repo-url>`
- or, after cloning : `git submodule update --init --recursive`

## steps

1. lexer
    -> tokens types : 
      - TOKEN_VARIABLE      // x, y, etc.
      - TOKEN_NUMBER_INT    // int
      - TOKEN_NUMBER_DOUBLE // double
      - TOKEN_POWER         // ^ or **
      - TOKEN_SIGN_PLUS     // +
      - TOKEN_SIGN_MINUS    // -
      - TOKEN_FACTOR_MULT   // *
      - TOKEN_FACTOR_DIV    // / or :
      - TOKEN_EQUAL         // =
      - END                 // null
2. parser
    -> terms : 
      - POSITION    // left or righ from =
      - SIGN        // + or -
      - COEFFICIENT // double
      - EXPONENT    // double
3. reduce
    -> polynom : 
      - sign
      - coefficient
      - exponent
4. print reduced form
    -> print reduced form
    -> if degree 1 :
      - if c = 0  -> print "any real is a solution"
      - if c != 0 -> print "no solution"
    -> if degree 2 :
      - print degree
    -> if degree 3 :
      - print degree
5. solve
    -> degree 1 : 
      -> ax + b = 0 <=> ax = -b <=> x = -b / a
      -> solution : 
        - a;                       // double
        - b;                       // double
        - solution_gcd;            // gcd(b, a)
        - solution_numerator;      // -b / gcd
        - solution_denominator;    //  a / gcd
        - solution;                // double (-b / a)
    -> degree 2 : 
      -> discriminant          : Δ = b² - 4ac
      -> Δ > 0  -> 2 solutions : x = ( -b / 2a ) +-  ( √|Δ| / 2a )
      -> Δ == 0 -> 1 solution  : x = ( -b / 2a )
      -> Δ < 0  -> 2 solutions : x = ( -b / 2a ) +- i( √|Δ| / 2a )
      -> solution : 
        - delta_sign;              // + or -
        - delta_absolute;          // |Δ|
        - delta_sqrt;              // √|Δ|

        - first_term_gcd;          // gcd(b, 2a)
        - first_term_numerator;    // -b / gcd
        - first_term_denominator;  // 2a / gcd
        - first_term;              // double (-b / 2a)

        - second_term_gcd;         // gcd(√|Δ|, 2a)
        - second_term_numerator;   // √|Δ| / gcd
        - second_term_denominator; // 2a / gcd
        - second_term;             // double (√|Δ| / 2a)

        - double solution1;        // first_term + second_term
        - double solution2;        // first_term - second_term
6. print solution

---

# sqrt implementation

finding the square root of x

## dichotomy method

the dichotomie method, or binary search, consist on dividing the range of research by 2 each time, and choosing the right one for the next iteration.

Ex : 

```
     solution
        ↓
|------------------------------ 1. define range bound_1 : 0
|-----------------------------| 2. define range bound_2 : x
|--------------+--------------| 3. take mid : (bound_1 + bound_2) / 2
|--------------|-------ø------| 4. choose range bound : bound_1 or bound_2

---------------|--------------- 1. range bound_1 = mid
|--------------|--------------- 2. range bound_2 = chosen previous bound
|------+-------|--------------- 3. mid
|--ø---|-------|--------------- 4. choose range

-------|----------------------- 1. range bound_1 = mid
-------|-------|--------------- 2. range bound_2 = chosen previous bound
-------|---+---|--------------- 3. mid
-------|---|-ø-|--------------- 4. choose range

-----------|------------------- 1. range bound_1 = mid
-------|---|------------------- 2. range bound_2 = chosen previous bound
-------|-+-|------------------- 3. mid
-------|-|ø|------------------- 4. choose range

---------|--------------------- 1. range bound_1 = mid
-------|-|--------------------- 2. range bound_2 = chosen previous bound
-------|+|--------------------- 3. mid
-------ø|---------------------- 4. choose range

--------|---------------------- --> solution
```


## Newton–Raphson method

it's like a self-correcting binary search, we get rid of the step "choose range", we use the formulae `x/v` to find the next range, with `x` being the number we are trying to get the sqaure root from, and `v` the value found at the previous step.

Ex : 

```
     solution
        ↓
------------------------------| 1. define range bound_1 : v
--|---------------------------| 2. choose range bound_2 : x/v
--|-------------+-------------| 3. take mid : (v + x/v) / 2

----------------|-------------- 1. range bound_1 : v = mid
------|---------|-------------- 2. range bound_2 : x/v
------|----+----|-------------- 3. mid

-----------|------------------- 1. range bound_1 : v = mid
-|---------|------------------- 2. range bound_2 : x/v
-|----+----|------------------- 3. mid

------|------------------------ 1. range bound_1 : v = mid
------|-------|---------------- 2. range bound_2 : x/v
------|---+---|---------------- 3. mid

----------|-------------------- 1. range bound_1 : v = mid
------|---|-------------------- 2. range bound_2 : x/v
------|-+-|-------------------- 3. mid

--------|---------------------- --> solution
```

### mathematical proof that each range is automatically in the right range :
  - if the value was higher than the answer, then new value is below old value, and vice versa
  - how ? : 
    - define `x`, solution `s = √x`, and value `v = (old_value + x / old_value) / 2`
    - supposition : if `v < s` , then `new_v > v`, else `new_v < v` : 
    - demonstration : 
      1. if `v < s` : 
            v < s
        <=> v < √x
        <=> v² < x (that's actually how we know that v < s)
        <=> v²/v < x/v
        <=> v < x/v
        -> and is s < x/v ? : 
            v < s
        <=> v < √x
        <=> v² < x (as previously)
        <=> v² < x²/x
        <=> v² * x < x²
        <=> (v * √x)² < x²
        <=> v * √x < x
        <=> v * √x < v * x/v
        <=> √x < x/v
        -> so indeed : if v < √x, then v < √x < x/v == v < s < x/v
        -> conclusion, the new range < v , x/v > contains the solution
      2. the same demonstration works for `v > s`

### here is a more intuitive demonstration, with x = 20 : 

1. **show that if `v² > x` (== `v > s`) then `v > s > x/v`, and if `v² < x` (== `v < s`) then `v < s < x/v` :**
  1.1. **for value too high `v > s` :**
    1.1.1 **why `v > x/v` :**
      - let's take initial value v = 5 :
      - is 5² the solution ? 5² == 25 -> so no, 5 is not the sqrt, it's too high
        ```
                  v                   v²
             0   (5)   10   15   20   25
        v  : |----|----|----|----|----|
        x/v: |---|---|---|---|---| <----- squiz it, so the previous 5 portions fit the x = 20 size
             0  (4)  8   12  16  20
                x/v              x
        ```
      - the value of the new portion is 4, and we can visually see that it's lower than the previous portion 5
      - so : `v > x/v`
      1.1.2 **why `s > x/v` :**
      - let's take the value v = 5 : 
      - we already showed that it's too high, now we will see that x/v == 20/5 is too low : 
        ```
                     v
                0   (5)   10   15   20   25
        v  :    |----|----|----|----|----|
        x/v:    |---|---|---|---|---|   <----- squizz
                0  *1  *2  *3  *4  *5       -> number of portions
                01234                       -> portion size
        (x/v)²: |---|---|---|---|
                0   4   8   12  16
        ```
      - the portion size is smaller than the number of portions, so it's too small to be the sqrt, indeed we visually see that this portion size `x/v` is a root of a smaller number : `(x/v)² == 16`
      - so : `s > x/v`
    1.1.3. **conclusion :**
      -     v > s
      - and v > x/v (<- this proof is not essential)
      - and s > x/v (<- we actually only need this proof)
      - so `v > s > x/v`
  
  1.2. **for value too high `v < s` :**
    - this is the same demonstration but in other direction, let's just summarize it :
    - let's take initial value v = 4 :
      ```
                      v           v²
                  0  (4)  8   12  16
      (1) v  :    |---|---|---|---|
      (2) x/v:    |----|----|----|----|   -----> stretch
      (3)         0   (5)   10   15   20
                      x/v             x
      (4)         0   *1   *2   *3   *4       -> number of portions
                  012345                      -> portion size
      (5) (x/v)²: |----|----|----|----|----|
                  0    5    10   15   20   25
      ```
    - (1) : 4 is not the sqrt of x == 20, it's too smalle : (4² == 16) < 20
    - (2) : stretch it, so the previous 4 portions fit the x = 20 size
    - (3) : the new portion x/v == 5, is more than v == 4, so `v < x/v`
    - (4) : portion size is bigger than number of portions, so it's too big to be the root
    - (5) : indeed, we see that the portion² == (x/v)² is bigger than x, so √x < x/v == `s < x/v`
    - so `v < s < x/v`
