summaryrefslogtreecommitdiff
path: root/src/corelib/render/software/agg_bspline.pas
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/render/software/agg_bspline.pas')
-rw-r--r--src/corelib/render/software/agg_bspline.pas956
1 files changed, 478 insertions, 478 deletions
diff --git a/src/corelib/render/software/agg_bspline.pas b/src/corelib/render/software/agg_bspline.pas
index 5ccdce1f..22b11487 100644
--- a/src/corelib/render/software/agg_bspline.pas
+++ b/src/corelib/render/software/agg_bspline.pas
@@ -1,478 +1,478 @@
-//----------------------------------------------------------------------------
-// Anti-Grain Geometry - Version 2.4 (Public License)
-// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
-//
-// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
-// Pascal Port By: Milan Marusinec alias Milano
-// milan@marusinec.sk
-// http://www.aggpas.org
-// Copyright (c) 2005-2006
-//
-// Permission to copy, use, modify, sell and distribute this software
-// is granted provided this copyright notice appears in all copies.
-// This software is provided "as is" without express or implied
-// warranty, and with no claim as to its suitability for any purpose.
-//
-//----------------------------------------------------------------------------
-// Contact: mcseem@antigrain.com
-// mcseemagg@yahoo.com
-// http://www.antigrain.com
-//
-//----------------------------------------------------------------------------
-//
-// class bspline
-//
-// [Pascal Port History] -----------------------------------------------------
-//
-// 23.06.2006-Milano: ptrcomp adjustments
-// 19.01.2006-Milano: Complete Unit Port
-// 18.01.2006-Milano: Unit port establishment
-//
-{ agg_bspline.pas }
-unit
- agg_bspline ;
-
-INTERFACE
-
-{$I agg_mode.inc }
-
-uses
- agg_basics ;
-
-{ TYPES DEFINITION }
-type
-//----------------------------------------------------------------bspline
-// A very simple class of Bi-cubic Spline interpolation.
-// First call init(num, x[], y[]) where num - number of source points,
-// x, y - arrays of X and Y values respectively. Here Y must be a function
-// of X. It means that all the X-coordinates must be arranged in the ascending
-// order.
-// Then call get(x) that calculates a value Y for the respective X.
-// The class supports extrapolation, i.e. you can call get(x) where x is
-// outside the given with init() X-range. Extrapolation is a simple linear
-// function.
- bspline = object
- m_max ,
- m_num : int;
-
- m_x ,
- m_y ,
- m_am : double_ptr;
-
- m_last_idx : int;
-
- constructor Construct; overload;
- constructor Construct(num : int ); overload;
- constructor Construct(num : int; x ,y : double_ptr ); overload;
- destructor Destruct;
-
- procedure init(max : int ); overload;
- procedure init(num : int; x ,y : double_ptr ); overload;
-
- procedure add_point(x ,y : double );
- procedure prepare;
-
- function get (x : double ) : double;
- function get_stateful(x : double ) : double;
-
- procedure bsearch(n : int; x : double_ptr; x0 : double; i : int_ptr );
-
- function extrapolation_left (x : double ) : double;
- function extrapolation_right(x : double ) : double;
-
- function interpolation(x : double; i : int ) : double;
-
- end;
-
-{ GLOBAL PROCEDURES }
-
-
-IMPLEMENTATION
-{ LOCAL VARIABLES & CONSTANTS }
-{ UNIT IMPLEMENTATION }
-{ CONSTRUCT }
-constructor bspline.Construct;
-begin
- m_max:=0;
- m_num:=0;
-
- m_x :=NIL;
- m_y :=NIL;
- m_am:=NIL;
-
- m_last_idx:=-1;
-
-end;
-
-{ CONSTRUCT }
-constructor bspline.Construct(num : int );
-begin
- Construct;
-
- init(num );
-
-end;
-
-{ CONSTRUCT }
-constructor bspline.Construct(num : int; x ,y : double_ptr );
-begin
- Construct;
-
- init(num ,x ,y );
-
-end;
-
-{ DESTRUCT }
-destructor bspline.Destruct;
-begin
- agg_freemem(pointer(m_am ) ,m_max * 3 * sizeof(double ) );
-
-end;
-
-{ INIT }
-procedure bspline.init(max : int );
-begin
- if (max > 2 ) and
- (max > m_max ) then
- begin
- agg_freemem(pointer(m_am ) ,m_max * 3 * sizeof(double ) );
- agg_getmem (pointer(m_am ) ,max * 3 * sizeof(double ) );
-
- m_max:=max;
-
- m_x:=double_ptr(ptrcomp(m_am ) + m_max * sizeof(double ) );
- m_y:=double_ptr(ptrcomp(m_am ) + m_max * 2 * sizeof(double ) );
-
- end;
-
- m_num :=0;
- m_last_idx:=-1;
-
-end;
-
-{ INIT }
-procedure bspline.init(num : int; x ,y : double_ptr );
-var
- i : int;
-
-begin
- if num > 2 then
- begin
- init(num );
-
- for i:=0 to num - 1 do
- begin
- add_point(x^ ,y^ );
-
- inc(ptrcomp(x ) ,sizeof(double ) );
- inc(ptrcomp(y ) ,sizeof(double ) );
-
- end;
-
- prepare;
-
- end;
-
- m_last_idx:=-1;
-
-end;
-
-{ ADD_POINT }
-procedure bspline.add_point;
-begin
- if m_num < m_max then
- begin
- double_ptr(ptrcomp(m_x ) + m_num * sizeof(double ) )^:=x;
- double_ptr(ptrcomp(m_y ) + m_num * sizeof(double ) )^:=y;
-
- inc(m_num );
-
- end;
-
-end;
-
-{ PREPARE }
-procedure bspline.prepare;
-var
- i ,k ,n1 ,sz : int;
- temp ,r ,s ,al : double_ptr;
- h ,p ,d ,f ,e : double;
-
-begin
- if m_num > 2 then
- begin
- for k:=0 to m_num - 1 do
- double_ptr(ptrcomp(m_am ) + k * sizeof(double ) )^:=0;
-
- n1:=3 * m_num;
- sz:=n1;
-
- agg_getmem(pointer(al ) ,n1 * sizeof(double ) );
-
- temp:=al;
-
- for k:=0 to n1 - 1 do
- double_ptr(ptrcomp(temp ) + k * sizeof(double ) )^:=0;
-
- r:=double_ptr(ptrcomp(temp ) + m_num * sizeof(double ) );
- s:=double_ptr(ptrcomp(temp ) + m_num * 2 * sizeof(double ) );
-
- n1:=m_num - 1;
- d :=double_ptr(ptrcomp(m_x ) + sizeof(double ) )^ - m_x^;
- e :=(double_ptr(ptrcomp(m_y ) + sizeof(double ) )^ - m_y^ ) / d;
-
- k:=1;
-
- while k < n1 do
- begin
- h:=d;
- d:=double_ptr(ptrcomp(m_x ) + (k + 1 ) * sizeof(double ) )^ - double_ptr(ptrcomp(m_x ) + k * sizeof(double ) )^;
- f:=e;
- e:=(double_ptr(ptrcomp(m_y ) + (k + 1 ) * sizeof(double ) )^ - double_ptr(ptrcomp(m_y ) + k * sizeof(double ) )^ ) / d;
-
- double_ptr(ptrcomp(al ) + k * sizeof(double ) )^:=d / (d + h );
- double_ptr(ptrcomp(r ) + k * sizeof(double ) )^ :=1.0 - double_ptr(ptrcomp(al ) + k * sizeof(double ) )^;
- double_ptr(ptrcomp(s ) + k * sizeof(double ) )^ :=6.0 * (e - f ) / (h + d );
-
- inc(k );
-
- end;
-
- k:=1;
-
- while k < n1 do
- begin
- p:=1.0 / (double_ptr(ptrcomp(r ) + k * sizeof(double ) )^ * double_ptr(ptrcomp(al ) + (k - 1 ) * sizeof(double ) )^ + 2.0 );
-
- double_ptr(ptrcomp(al ) + k * sizeof(double ) )^:=
- double_ptr(ptrcomp(al ) + k * sizeof(double ) )^ * -p;
-
- double_ptr(ptrcomp(s ) + k * sizeof(double ) )^ :=
- (double_ptr(ptrcomp(s ) + k * sizeof(double ) )^ -
- double_ptr(ptrcomp(r ) + k * sizeof(double ) )^ *
- double_ptr(ptrcomp(s ) + (k - 1 ) * sizeof(double ) )^ ) * p;
-
- inc(k );
-
- end;
-
- double_ptr(ptrcomp(m_am ) + n1 * sizeof(double ) )^:=0.0;
-
- double_ptr(ptrcomp(al ) + (n1 - 1 ) * sizeof(double ) )^:=
- double_ptr(ptrcomp(s ) + (n1 - 1 ) * sizeof(double ) )^;
-
- double_ptr(ptrcomp(m_am ) + (n1 - 1 ) * sizeof(double ) )^:=
- double_ptr(ptrcomp(al ) + (n1 - 1 ) * sizeof(double ) )^;
-
- k:=n1 - 2;
- i:=0;
-
- while i < m_num - 2 do
- begin
- double_ptr(ptrcomp(al ) + k * sizeof(double ) )^:=
- double_ptr(ptrcomp(al ) + k * sizeof(double ) )^ *
- double_ptr(ptrcomp(al ) + (k + 1 ) * sizeof(double ) )^ +
- double_ptr(ptrcomp(s ) + k * sizeof(double ) )^;
-
- double_ptr(ptrcomp(m_am ) + k * sizeof(double ) )^:=
- double_ptr(ptrcomp(al ) + k * sizeof(double ) )^;
-
- inc(i );
- dec(k );
-
- end;
-
- agg_freemem(pointer(al ) ,sz * sizeof(double ) );
-
- end;
-
- m_last_idx:=-1;
-
-end;
-
-{ GET }
-function bspline.get;
-var
- i : int;
-
-begin
- if m_num > 2 then
- begin
- // Extrapolation on the left
- if x < m_x^ then
- begin
- result:=extrapolation_left(x );
-
- exit;
-
- end;
-
- // Extrapolation on the right
- if x >= double_ptr(ptrcomp(m_x ) + (m_num - 1 ) * sizeof(double ) )^ then
- begin
- result:=extrapolation_right(x );
-
- exit;
-
- end;
-
- // Interpolation
- bsearch(m_num ,m_x ,x ,@i );
-
- result:=interpolation(x ,i );
-
- exit;
-
- end;
-
- result:=0.0;
-
-end;
-
-{ GET_STATEFUL }
-function bspline.get_stateful;
-begin
- if m_num > 2 then
- begin
- // Extrapolation on the left
- if x < m_x^ then
- begin
- result:=extrapolation_left(x );
-
- exit;
-
- end;
-
- // Extrapolation on the right
- if x >= double_ptr(ptrcomp(m_x ) + (m_num - 1 ) * sizeof(double ) )^ then
- begin
- result:=extrapolation_right(x );
-
- exit;
-
- end;
-
- if m_last_idx >= 0 then
- begin
- // Check if x is not in current range
- if (x < double_ptr(ptrcomp(m_x ) + m_last_idx * sizeof(double ) )^ ) or
- (x > double_ptr(ptrcomp(m_x ) + (m_last_idx + 1 ) * sizeof(double ) )^ ) then
- // Check if x between next points (most probably)
- if (m_last_idx < m_num - 2 ) and
- (x >= double_ptr(ptrcomp(m_x ) + (m_last_idx + 1 ) * sizeof(double ) )^ ) and
- (x <= double_ptr(ptrcomp(m_x ) + (m_last_idx + 2 ) * sizeof(double ) )^ ) then
- inc(m_last_idx )
- else
- if (m_last_idx > 0 ) and
- (x >= double_ptr(ptrcomp(m_x ) + (m_last_idx - 1 ) * sizeof(double ) )^ ) and
- (x <= double_ptr(ptrcomp(m_x ) + m_last_idx * sizeof(double ) )^ ) then
- // x is between pevious points
- dec(m_last_idx )
- else
- // Else perform full search
- bsearch(m_num ,m_x ,x ,@m_last_idx );
-
- result:=interpolation(x ,m_last_idx );
-
- exit;
-
- end
- else
- begin
- // Interpolation
- bsearch(m_num ,m_x ,x ,@m_last_idx );
-
- result:=interpolation(x ,m_last_idx );
-
- exit;
-
- end;
-
- end;
-
- result:=0.0;
-
-end;
-
-{ BSEARCH }
-procedure bspline.bsearch;
-var
- j ,k : int;
-
-begin
- j :=n - 1;
- i^:=0;
-
- while j - i^ > 1 do
- begin
- k:=shr_int32(i^ + j ,1 );
-
- if x0 < double_ptr(ptrcomp(x ) + k * sizeof(double ) )^ then
- j:=k
- else
- i^:=k;
-
- end;
-
-end;
-
-{ EXTRAPOLATION_LEFT }
-function bspline.extrapolation_left;
-var
- d : double;
-
-begin
- d:=double_ptr(ptrcomp(m_x ) + sizeof(double ) )^ - m_x^;
-
- result:=
- (-d * double_ptr(ptrcomp(m_am ) + sizeof(double ) )^ / 6 +
- (double_ptr(ptrcomp(m_y ) + sizeof(double ) )^ - m_y^ ) / d ) *
- (x - m_x^ ) + m_y^;
-
-end;
-
-{ EXTRAPOLATION_RIGHT }
-function bspline.extrapolation_right;
-var
- d : double;
-
-begin
- d:=
- double_ptr(ptrcomp(m_x ) + (m_num - 1 ) * sizeof(double ) )^ -
- double_ptr(ptrcomp(m_x ) + (m_num - 2 ) * sizeof(double ) )^;
-
- result:=
- (d * double_ptr(ptrcomp(m_am ) + (m_num - 2 ) * sizeof(double ) )^ / 6 +
- (double_ptr(ptrcomp(m_y ) + (m_num - 1 ) * sizeof(double ) )^ -
- double_ptr(ptrcomp(m_y ) + (m_num - 2 ) * sizeof(double ) )^ ) / d ) *
- (x - double_ptr(ptrcomp(m_x ) + (m_num - 1 ) * sizeof(double ) )^ ) +
- double_ptr(ptrcomp(m_y ) + (m_num - 1 ) * sizeof(double ) )^;
-
-end;
-
-{ INTERPOLATION }
-function bspline.interpolation;
-var
- j : int;
-
- d ,h ,r ,p : double;
-
-begin
- j:=i + 1;
- d:=double_ptr(ptrcomp(m_x ) + i * sizeof(double ) )^ - double_ptr(ptrcomp(m_x ) + j * sizeof(double ) )^;
- h:=x - double_ptr(ptrcomp(m_x ) + j * sizeof(double ) )^;
- r:=double_ptr(ptrcomp(m_x ) + i * sizeof(double ) )^ - x;
- p:=d * d / 6.0;
-
- result:=
- (double_ptr(ptrcomp(m_am ) + j * sizeof(double ) )^ * r * r * r +
- double_ptr(ptrcomp(m_am ) + i * sizeof(double ) )^ * h * h * h ) / 6.0 / d +
- ((double_ptr(ptrcomp(m_y ) + j * sizeof(double ) )^ -
- double_ptr(ptrcomp(m_am ) + j * sizeof(double ) )^ * p ) * r +
- (double_ptr(ptrcomp(m_y ) + i * sizeof(double ) )^ -
- double_ptr(ptrcomp(m_am ) + i * sizeof(double ) )^ * p ) * h ) / d;
-
-end;
-
-END.
-
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// class bspline
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 19.01.2006-Milano: Complete Unit Port
+// 18.01.2006-Milano: Unit port establishment
+//
+{ agg_bspline.pas }
+unit
+ agg_bspline ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ agg_basics ;
+
+{ TYPES DEFINITION }
+type
+//----------------------------------------------------------------bspline
+// A very simple class of Bi-cubic Spline interpolation.
+// First call init(num, x[], y[]) where num - number of source points,
+// x, y - arrays of X and Y values respectively. Here Y must be a function
+// of X. It means that all the X-coordinates must be arranged in the ascending
+// order.
+// Then call get(x) that calculates a value Y for the respective X.
+// The class supports extrapolation, i.e. you can call get(x) where x is
+// outside the given with init() X-range. Extrapolation is a simple linear
+// function.
+ bspline = object
+ m_max ,
+ m_num : int;
+
+ m_x ,
+ m_y ,
+ m_am : double_ptr;
+
+ m_last_idx : int;
+
+ constructor Construct; overload;
+ constructor Construct(num : int ); overload;
+ constructor Construct(num : int; x ,y : double_ptr ); overload;
+ destructor Destruct;
+
+ procedure init(max : int ); overload;
+ procedure init(num : int; x ,y : double_ptr ); overload;
+
+ procedure add_point(x ,y : double );
+ procedure prepare;
+
+ function get (x : double ) : double;
+ function get_stateful(x : double ) : double;
+
+ procedure bsearch(n : int; x : double_ptr; x0 : double; i : int_ptr );
+
+ function extrapolation_left (x : double ) : double;
+ function extrapolation_right(x : double ) : double;
+
+ function interpolation(x : double; i : int ) : double;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor bspline.Construct;
+begin
+ m_max:=0;
+ m_num:=0;
+
+ m_x :=NIL;
+ m_y :=NIL;
+ m_am:=NIL;
+
+ m_last_idx:=-1;
+
+end;
+
+{ CONSTRUCT }
+constructor bspline.Construct(num : int );
+begin
+ Construct;
+
+ init(num );
+
+end;
+
+{ CONSTRUCT }
+constructor bspline.Construct(num : int; x ,y : double_ptr );
+begin
+ Construct;
+
+ init(num ,x ,y );
+
+end;
+
+{ DESTRUCT }
+destructor bspline.Destruct;
+begin
+ agg_freemem(pointer(m_am ) ,m_max * 3 * sizeof(double ) );
+
+end;
+
+{ INIT }
+procedure bspline.init(max : int );
+begin
+ if (max > 2 ) and
+ (max > m_max ) then
+ begin
+ agg_freemem(pointer(m_am ) ,m_max * 3 * sizeof(double ) );
+ agg_getmem (pointer(m_am ) ,max * 3 * sizeof(double ) );
+
+ m_max:=max;
+
+ m_x:=double_ptr(ptrcomp(m_am ) + m_max * sizeof(double ) );
+ m_y:=double_ptr(ptrcomp(m_am ) + m_max * 2 * sizeof(double ) );
+
+ end;
+
+ m_num :=0;
+ m_last_idx:=-1;
+
+end;
+
+{ INIT }
+procedure bspline.init(num : int; x ,y : double_ptr );
+var
+ i : int;
+
+begin
+ if num > 2 then
+ begin
+ init(num );
+
+ for i:=0 to num - 1 do
+ begin
+ add_point(x^ ,y^ );
+
+ inc(ptrcomp(x ) ,sizeof(double ) );
+ inc(ptrcomp(y ) ,sizeof(double ) );
+
+ end;
+
+ prepare;
+
+ end;
+
+ m_last_idx:=-1;
+
+end;
+
+{ ADD_POINT }
+procedure bspline.add_point;
+begin
+ if m_num < m_max then
+ begin
+ double_ptr(ptrcomp(m_x ) + m_num * sizeof(double ) )^:=x;
+ double_ptr(ptrcomp(m_y ) + m_num * sizeof(double ) )^:=y;
+
+ inc(m_num );
+
+ end;
+
+end;
+
+{ PREPARE }
+procedure bspline.prepare;
+var
+ i ,k ,n1 ,sz : int;
+ temp ,r ,s ,al : double_ptr;
+ h ,p ,d ,f ,e : double;
+
+begin
+ if m_num > 2 then
+ begin
+ for k:=0 to m_num - 1 do
+ double_ptr(ptrcomp(m_am ) + k * sizeof(double ) )^:=0;
+
+ n1:=3 * m_num;
+ sz:=n1;
+
+ agg_getmem(pointer(al ) ,n1 * sizeof(double ) );
+
+ temp:=al;
+
+ for k:=0 to n1 - 1 do
+ double_ptr(ptrcomp(temp ) + k * sizeof(double ) )^:=0;
+
+ r:=double_ptr(ptrcomp(temp ) + m_num * sizeof(double ) );
+ s:=double_ptr(ptrcomp(temp ) + m_num * 2 * sizeof(double ) );
+
+ n1:=m_num - 1;
+ d :=double_ptr(ptrcomp(m_x ) + sizeof(double ) )^ - m_x^;
+ e :=(double_ptr(ptrcomp(m_y ) + sizeof(double ) )^ - m_y^ ) / d;
+
+ k:=1;
+
+ while k < n1 do
+ begin
+ h:=d;
+ d:=double_ptr(ptrcomp(m_x ) + (k + 1 ) * sizeof(double ) )^ - double_ptr(ptrcomp(m_x ) + k * sizeof(double ) )^;
+ f:=e;
+ e:=(double_ptr(ptrcomp(m_y ) + (k + 1 ) * sizeof(double ) )^ - double_ptr(ptrcomp(m_y ) + k * sizeof(double ) )^ ) / d;
+
+ double_ptr(ptrcomp(al ) + k * sizeof(double ) )^:=d / (d + h );
+ double_ptr(ptrcomp(r ) + k * sizeof(double ) )^ :=1.0 - double_ptr(ptrcomp(al ) + k * sizeof(double ) )^;
+ double_ptr(ptrcomp(s ) + k * sizeof(double ) )^ :=6.0 * (e - f ) / (h + d );
+
+ inc(k );
+
+ end;
+
+ k:=1;
+
+ while k < n1 do
+ begin
+ p:=1.0 / (double_ptr(ptrcomp(r ) + k * sizeof(double ) )^ * double_ptr(ptrcomp(al ) + (k - 1 ) * sizeof(double ) )^ + 2.0 );
+
+ double_ptr(ptrcomp(al ) + k * sizeof(double ) )^:=
+ double_ptr(ptrcomp(al ) + k * sizeof(double ) )^ * -p;
+
+ double_ptr(ptrcomp(s ) + k * sizeof(double ) )^ :=
+ (double_ptr(ptrcomp(s ) + k * sizeof(double ) )^ -
+ double_ptr(ptrcomp(r ) + k * sizeof(double ) )^ *
+ double_ptr(ptrcomp(s ) + (k - 1 ) * sizeof(double ) )^ ) * p;
+
+ inc(k );
+
+ end;
+
+ double_ptr(ptrcomp(m_am ) + n1 * sizeof(double ) )^:=0.0;
+
+ double_ptr(ptrcomp(al ) + (n1 - 1 ) * sizeof(double ) )^:=
+ double_ptr(ptrcomp(s ) + (n1 - 1 ) * sizeof(double ) )^;
+
+ double_ptr(ptrcomp(m_am ) + (n1 - 1 ) * sizeof(double ) )^:=
+ double_ptr(ptrcomp(al ) + (n1 - 1 ) * sizeof(double ) )^;
+
+ k:=n1 - 2;
+ i:=0;
+
+ while i < m_num - 2 do
+ begin
+ double_ptr(ptrcomp(al ) + k * sizeof(double ) )^:=
+ double_ptr(ptrcomp(al ) + k * sizeof(double ) )^ *
+ double_ptr(ptrcomp(al ) + (k + 1 ) * sizeof(double ) )^ +
+ double_ptr(ptrcomp(s ) + k * sizeof(double ) )^;
+
+ double_ptr(ptrcomp(m_am ) + k * sizeof(double ) )^:=
+ double_ptr(ptrcomp(al ) + k * sizeof(double ) )^;
+
+ inc(i );
+ dec(k );
+
+ end;
+
+ agg_freemem(pointer(al ) ,sz * sizeof(double ) );
+
+ end;
+
+ m_last_idx:=-1;
+
+end;
+
+{ GET }
+function bspline.get;
+var
+ i : int;
+
+begin
+ if m_num > 2 then
+ begin
+ // Extrapolation on the left
+ if x < m_x^ then
+ begin
+ result:=extrapolation_left(x );
+
+ exit;
+
+ end;
+
+ // Extrapolation on the right
+ if x >= double_ptr(ptrcomp(m_x ) + (m_num - 1 ) * sizeof(double ) )^ then
+ begin
+ result:=extrapolation_right(x );
+
+ exit;
+
+ end;
+
+ // Interpolation
+ bsearch(m_num ,m_x ,x ,@i );
+
+ result:=interpolation(x ,i );
+
+ exit;
+
+ end;
+
+ result:=0.0;
+
+end;
+
+{ GET_STATEFUL }
+function bspline.get_stateful;
+begin
+ if m_num > 2 then
+ begin
+ // Extrapolation on the left
+ if x < m_x^ then
+ begin
+ result:=extrapolation_left(x );
+
+ exit;
+
+ end;
+
+ // Extrapolation on the right
+ if x >= double_ptr(ptrcomp(m_x ) + (m_num - 1 ) * sizeof(double ) )^ then
+ begin
+ result:=extrapolation_right(x );
+
+ exit;
+
+ end;
+
+ if m_last_idx >= 0 then
+ begin
+ // Check if x is not in current range
+ if (x < double_ptr(ptrcomp(m_x ) + m_last_idx * sizeof(double ) )^ ) or
+ (x > double_ptr(ptrcomp(m_x ) + (m_last_idx + 1 ) * sizeof(double ) )^ ) then
+ // Check if x between next points (most probably)
+ if (m_last_idx < m_num - 2 ) and
+ (x >= double_ptr(ptrcomp(m_x ) + (m_last_idx + 1 ) * sizeof(double ) )^ ) and
+ (x <= double_ptr(ptrcomp(m_x ) + (m_last_idx + 2 ) * sizeof(double ) )^ ) then
+ inc(m_last_idx )
+ else
+ if (m_last_idx > 0 ) and
+ (x >= double_ptr(ptrcomp(m_x ) + (m_last_idx - 1 ) * sizeof(double ) )^ ) and
+ (x <= double_ptr(ptrcomp(m_x ) + m_last_idx * sizeof(double ) )^ ) then
+ // x is between pevious points
+ dec(m_last_idx )
+ else
+ // Else perform full search
+ bsearch(m_num ,m_x ,x ,@m_last_idx );
+
+ result:=interpolation(x ,m_last_idx );
+
+ exit;
+
+ end
+ else
+ begin
+ // Interpolation
+ bsearch(m_num ,m_x ,x ,@m_last_idx );
+
+ result:=interpolation(x ,m_last_idx );
+
+ exit;
+
+ end;
+
+ end;
+
+ result:=0.0;
+
+end;
+
+{ BSEARCH }
+procedure bspline.bsearch;
+var
+ j ,k : int;
+
+begin
+ j :=n - 1;
+ i^:=0;
+
+ while j - i^ > 1 do
+ begin
+ k:=shr_int32(i^ + j ,1 );
+
+ if x0 < double_ptr(ptrcomp(x ) + k * sizeof(double ) )^ then
+ j:=k
+ else
+ i^:=k;
+
+ end;
+
+end;
+
+{ EXTRAPOLATION_LEFT }
+function bspline.extrapolation_left;
+var
+ d : double;
+
+begin
+ d:=double_ptr(ptrcomp(m_x ) + sizeof(double ) )^ - m_x^;
+
+ result:=
+ (-d * double_ptr(ptrcomp(m_am ) + sizeof(double ) )^ / 6 +
+ (double_ptr(ptrcomp(m_y ) + sizeof(double ) )^ - m_y^ ) / d ) *
+ (x - m_x^ ) + m_y^;
+
+end;
+
+{ EXTRAPOLATION_RIGHT }
+function bspline.extrapolation_right;
+var
+ d : double;
+
+begin
+ d:=
+ double_ptr(ptrcomp(m_x ) + (m_num - 1 ) * sizeof(double ) )^ -
+ double_ptr(ptrcomp(m_x ) + (m_num - 2 ) * sizeof(double ) )^;
+
+ result:=
+ (d * double_ptr(ptrcomp(m_am ) + (m_num - 2 ) * sizeof(double ) )^ / 6 +
+ (double_ptr(ptrcomp(m_y ) + (m_num - 1 ) * sizeof(double ) )^ -
+ double_ptr(ptrcomp(m_y ) + (m_num - 2 ) * sizeof(double ) )^ ) / d ) *
+ (x - double_ptr(ptrcomp(m_x ) + (m_num - 1 ) * sizeof(double ) )^ ) +
+ double_ptr(ptrcomp(m_y ) + (m_num - 1 ) * sizeof(double ) )^;
+
+end;
+
+{ INTERPOLATION }
+function bspline.interpolation;
+var
+ j : int;
+
+ d ,h ,r ,p : double;
+
+begin
+ j:=i + 1;
+ d:=double_ptr(ptrcomp(m_x ) + i * sizeof(double ) )^ - double_ptr(ptrcomp(m_x ) + j * sizeof(double ) )^;
+ h:=x - double_ptr(ptrcomp(m_x ) + j * sizeof(double ) )^;
+ r:=double_ptr(ptrcomp(m_x ) + i * sizeof(double ) )^ - x;
+ p:=d * d / 6.0;
+
+ result:=
+ (double_ptr(ptrcomp(m_am ) + j * sizeof(double ) )^ * r * r * r +
+ double_ptr(ptrcomp(m_am ) + i * sizeof(double ) )^ * h * h * h ) / 6.0 / d +
+ ((double_ptr(ptrcomp(m_y ) + j * sizeof(double ) )^ -
+ double_ptr(ptrcomp(m_am ) + j * sizeof(double ) )^ * p ) * r +
+ (double_ptr(ptrcomp(m_y ) + i * sizeof(double ) )^ -
+ double_ptr(ptrcomp(m_am ) + i * sizeof(double ) )^ * p ) * h ) / d;
+
+end;
+
+END.
+