From 689d2c8902f16fa460804847e9d3143a30cdc8f7 Mon Sep 17 00:00:00 2001
From: john verzani <jverzani@gmail.com>
Date: Thu, 25 Apr 2024 21:50:40 -0400
Subject: [PATCH] Lim (#66)

* different display for lim

* one more tweak

* doc string update
---
 Project.toml  |   2 +-
 src/limits.jl | 145 +++++++++++++++++++++++++++++++++++++++-----------
 2 files changed, 114 insertions(+), 33 deletions(-)

diff --git a/Project.toml b/Project.toml
index ec7eb6f..184f0c3 100644
--- a/Project.toml
+++ b/Project.toml
@@ -1,6 +1,6 @@
 name = "CalculusWithJulia"
 uuid = "a2e0e22d-7d4c-5312-9169-8b992201a882"
-version = "0.2.2"
+version = "0.2.3"
 
 [deps]
 Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
diff --git a/src/limits.jl b/src/limits.jl
index 2e5a2c5..b2fdc2d 100644
--- a/src/limits.jl
+++ b/src/limits.jl
@@ -1,20 +1,41 @@
 """
-    lim(f, c; n=5, dir="+")
+    lim(f, c; n=6, m=1, dir="+-")
     lim(f, c, dir; n-5)
 
 Means to generate numeric table of values of `f` as `h` gets close to `c`.
 
+* `n`, `m`: powers of `10` to add (subtract) to (from) `c`.
+* `dir`: Either `"+-"` (show left and right), `"+"` (right limit), or `"-"` (left limit). Can also use functions `+`, `-`, `±`.
+
 Example:
+
 ```
-f(x) = sin(x) / x
-lim(f, 0)
+julia> f(x) = sin(x) / x
+f (generic function with 1 method)
+
+julia> lim(f, 0)
+ 0.1        0.9983341664682815
+ 0.01       0.9999833334166665
+ 0.001      0.9999998333333416
+ 0.0001     0.9999999983333334
+ 1.0e-5     0.9999999999833332
+ 1.0e-6     0.9999999999998334
+   ⋮          ⋮
+   c          L?
+   ⋮          ⋮
+-1.0e-6     0.9999999999998334
+-1.0e-5     0.9999999999833332
+-0.0001     0.9999999983333334
+-0.001      0.9999998333333416
+-0.01       0.9999833334166665
+-0.1        0.9983341664682815
 ```
 """
-function lim(f::Function, c::Real; n::Int=6, m::Int=1, dir="+")
+function lim(f::Function, c::Real; n::Int=6, m::Int=1, dir="+-")
     dir = string(dir)
     Limit(f, c, n, m, dir)
 end
-lim(f::Function, c::Real, dir; n::Integer=5, m::Integer=1) = lim(f,c; n, m, dir=string(dir))
+lim(f::Function, c::Real, dir; n::Int=6, m::Int=1) = lim(f,c; n, m, dir=string(dir))
 
 
 struct Limit{F,R}
@@ -26,41 +47,101 @@ struct Limit{F,R}
 end
 
 # try to better align numbers
+_l8(x) = length(string(x)) ÷ 8
+
 function Base.show(io::IO, L::Limit)
     (; f,c,n,m,dir) = L
+
+    ms = maximum(length ∘ string, (c-1/10^n, c+1/10^n))
+    sc = (sign(c-m) * sign(c+m) < 0)
+
+    h = 1/10^n
+    nt = 2 + maximum(_l8, (c-h, c+h)) + (n ÷ 8)
+
+    if dir == "+" || dir == "+-" || dir == "±"
+        show₊(io, L; sc, ms)
+    end
+    print_dots(io, "c", "L?"; sc, ms)
+    if dir == "-" || dir == "--" || dir == "+-" || dir == "±"
+        show₋(io, L; sc, ms)
+    end
+    nothing
+end
+
+function show₊(io::IO, L::Limit; sc=false, ms=0)
+
+    (; f,c,n,m,dir) = L
+
     hs = [1/10^i for i in m:n] # close to 0
-    if dir == "+"
-	xs = c .+ hs
-    else
-	xs = c .- hs
+    xsᵣ = c .+ hs
+    ysᵣ = string.(f.(xsᵣ))
+
+    last_y = nothing
+
+    for (x,y) ∈ zip(xsᵣ, ysᵣ)
+        print_next(io, x, y, last_y; sc, ms)
+        last_y = y
+        println(io, "")
     end
-    ys = string.(map(f, xs))
 
-    _l8(x) = length(string(x)) ÷ 8
-    nt = 2 + _l8(first(xs)) + (n ÷ 8)
-    nl = false
+    print_dots(io; sc, ms)
+end
+
+# show - case
+function show₋(io::IO, L::Limit; sc=false, ms=0)
+    (; f,c,n,m,dir) = L
+
+    hs = [1/10^i for i in n:-1:m] # close to 0
+    xsₗ = c .- hs
+    ysₗ = string.(f.(xsₗ))
+
     last_y = nothing
-    for (x,y) ∈ zip(xs, ys)
-        nl && println(io, "")
-        nl = true
-        print(io, x)
-        m = _l8(x)
-        print(io, "\t"^(nt-m))
-        if isnothing(last_y)
-            print(io, y)
+
+    i, l = 1, length(ysₗ)
+    nl = true
+    #dir == "-" && print_dots(io; sc, ms)
+    print_dots(io; sc, ms)
+    for (x, y) ∈ zip(xsₗ, ysₗ)
+        if i == l
+            last_y = nothing
+            nl = false
         else
-            flag = true
-            ly = length(last_y)
-            for (i,yᵢ) ∈ enumerate(y)
-                if flag && i <= ly && yᵢ == last_y[i]
-                    printstyled(io, yᵢ; bold=true)
-                else
-                    print(io, yᵢ)
-                    flag=false
-                end
+            last_y = ysₗ[i+1]
+            i += 1
+        end
+        print_next(io, x, y, last_y; sc, ms)
+        nl && println(io, "")
+    end
+
+end
+
+# print dots or c L
+function print_dots(io::IO, l="⋮", r="⋮"; sc, ms)
+    d = ms ÷ 2
+    println(io, " "^d, l, " "^(4 +2d), r)
+end
+
+
+# print next number referring to last one for styling
+function print_next(io::IO, x, y, last_y=nothing; sc=false, ms=0)
+    xₛ = string(x)
+    sc && x > 0 && (xₛ = " " * xₛ)
+
+    print(io, xₛ)
+    l = length(xₛ)
+    print(io, " "^(ms - l + 5))
+    if isnothing(last_y)
+        print(io, y)
+    else
+        flag = true
+        ly = length(last_y)
+        for (i,yᵢ) ∈ enumerate(y)
+            if flag && i <= ly && yᵢ == last_y[i]
+                printstyled(io, yᵢ; bold=true)
+            else
+                print(io, yᵢ)
+                flag=false
             end
         end
-        last_y = y
     end
-    nothing
 end