Skip to content

Commit bd810ba

Browse files
committed
improve lagrange and lagrange_poly functions
1 parent 9559c2b commit bd810ba

File tree

1 file changed

+29
-30
lines changed

1 file changed

+29
-30
lines changed

src/forcolormap_utils.f90

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,12 @@ end function factorial
9292

9393
!> Create colormap from Lagrange interpolation of control colors
9494
pure function lagrange(colors, levels) result(map)
95-
integer, dimension(:,:), intent(in) :: colors
95+
integer, intent(in) :: colors(:,:)
9696
integer, intent(in), optional :: levels
97-
integer, dimension(:,:), allocatable :: map
98-
real(wp), dimension(:,:), allocatable :: map_r
99-
integer :: order, i, j, levels_
100-
real(wp) :: t
97+
integer, allocatable :: map(:,:)
98+
integer :: order, i, j, n, levels_
99+
real(wp) :: t, r, g, b
100+
real(wp), allocatable :: L(:)
101101

102102
! Set default value for levels
103103
if (present(levels)) then
@@ -110,51 +110,50 @@ pure function lagrange(colors, levels) result(map)
110110
order = size(colors, 1) - 1
111111
if (order < 1) error stop "Error: At least two control colors are required for Lagrange interpolation."
112112

113-
allocate(map_r(levels_,3), map(levels_,3)) ! 3 for RGB
113+
allocate(map(levels_, 3))
114+
n = order + 1
114115
do i = 1, levels_
115116
t = real(i-1, wp) / real(levels_-1, wp)
116-
map_r(i,:) = 0.0_wp
117-
do j = 0, order
118-
map_r(i,1) = dot_product(lagrange_poly(t,order+1), real(colors(:,1), wp))
119-
map_r(i,2) = dot_product(lagrange_poly(t,order+1), real(colors(:,2), wp))
120-
map_r(i,3) = dot_product(lagrange_poly(t,order+1), real(colors(:,3), wp))
117+
L = lagrange_poly(t, n)
118+
r = 0.0_wp
119+
g = 0.0_wp
120+
b = 0.0_wp
121+
do j = 1, n
122+
r = r + L(j) * real(colors(j,1), wp)
123+
g = g + L(j) * real(colors(j,2), wp)
124+
b = b + L(j) * real(colors(j,3), wp)
121125
end do
122-
map(i,1) = min(255, max(0, nint(map_r(i,1))))
123-
map(i,2) = min(255, max(0, nint(map_r(i,2))))
124-
map(i,3) = min(255, max(0, nint(map_r(i,3))))
126+
map(i,1) = min(255, max(0, nint(r)))
127+
map(i,2) = min(255, max(0, nint(g)))
128+
map(i,3) = min(255, max(0, nint(b)))
125129
end do
126130
end function lagrange
127131

128132
!> Interpolates a Lagrange polynomial defined by n equidistant points between 0 and 1
129133
pure function lagrange_poly(t, n) result(B)
130134
real(wp), intent(in) :: t
131-
integer, intent(in) :: n !! order + 1
132-
real(wp), allocatable :: B(:)
135+
integer, intent(in) :: n
136+
real(wp) :: B(n)
133137
integer :: i, l
134-
real(wp), dimension(:), allocatable :: Xth
138+
real(wp) :: inv, xi, xl
135139

136-
! Create an array of n equidistant points between 0 and 1
137-
allocate(Xth(n), source = 0.0_wp)
138-
do i = 1, n - 1
139-
Xth(i) = 0.0_wp + real(i - 1, wp) * (1.0_wp - (0.0_wp)) / real(n - 1, wp)
140-
end do
141-
Xth(n) = 1.0_wp
142-
143-
allocate(B(n), source = 1.0_wp)
144-
l = 0
145-
i = 0
140+
if (n <= 1) error stop "Error: Number of points n must be greater than 1 in lagrange_poly."
141+
if (t < 0.0_wp .or. t > 1.0_wp) error stop "Error: t must be in [0,1] in lagrange_poly."
142+
B = 1.0_wp
143+
inv = 1.0_wp/real(n-1, wp)
146144
do i = 1, n
145+
xi = real(i-1, wp) * inv
147146
do l = 1, n
148147
if (l /= i) then
149-
if (abs(Xth(i) - Xth(l)) >= tiny(0.0_wp)) then
150-
B(i) = B(i)*(t - Xth(l))/(Xth(i) - Xth(l))
148+
xl = real(l-1, wp) * inv
149+
if (abs(xi-xl) >= tiny(0.0_wp)) then
150+
B(i) = B(i)*(t-xl)/(xi-xl)
151151
end if
152152
end if
153153
end do
154154
end do
155155
end function lagrange_poly
156156

157-
158157
!> Normalize the input real array to the range [0, 1]
159158
pure function scale_real_real(real_array,a,b) result(real_scaled_array)
160159
real(wp), dimension(:), intent(in) :: real_array

0 commit comments

Comments
 (0)