arrinsert.pro
5.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
;+
; NAME:
; ARRINSERT
;
; AUTHOR:
; Craig B. Markwardt, NASA/GSFC Code 662, Greenbelt, MD 20770
; craigm@lheamail.gsfc.nasa.gov
;
; PURPOSE:
; Insert one array into another
;
; CALLING SEQUENCE:
; NEWARR = ARRINSERT(INIT, INSERT, [AT=POSITION] )
;
; DESCRIPTION:
;
; ARRINSERT inserts the contents of one array (INSERT) into
; another (INIT), and returns the new array (NEWARR).
;
; ARRINSERT will handle empty lists, which are represented as
; undefined variables. If both input arrays are empty, then the
; scalar -1L is returned, and the keyword COUNT is set to 0L.
;
; INPUTS:
;
; INIT - the initial array, into which INSERT will be inserted. Any
; data type, including structures, is allowed. Regardless of
; the dimensions of INIT, it is treated as a one-dimensional
; array. If OVERWRITE is not set, then INIT itself is
; unmodified.
;
; INSERT - the array to be inserted into INIT, which must be of the
; same or similar type to INIT. If INSERT is empty, then
; INIT is returned unchanged. Regardless of the dimensions
; of INSERT, it is treated as a one-dimensional array.
;
; KEYWORDS:
;
; AT - a long integer indicating the position of the newly inserted
; sub-array. If AT is non-negative, then INSERT will appear
; at NEWARR[AT]. If AT is negative, then INSERT will appear
; at NEWARR[AT + (N+1)] where N is the number of elements in
; INIT, which is to say if AT is negative, it indexes from the
; end side of the array rather than the beginning. Thus,
; setting AT=-1 will concatenate INIT and INSERT.
;
; Default: 0L (INSERT appears at beginning of INIT)
;
; OVERWRITE - if set, then the initial array INIT will be
; overwritten by the new array. Upon exit INIT becomes
; undefined.
;
; COUNT - upon return, the number of elements in the resulting
; array.
;
; EMPTY1, EMPTY2 - if set, then INIT (for EMPTY1) or INSERT (for
; EMPTY2) are assumed to be empty (i.e., to have
; zero elements). The actual values passed as INIT
; or INSERT are then ignored.
;
; RETURNS:
;
; The new array, which is always one-dimensional. If COUNT is zero,
; then the scalar -1L is returned.
;
; EXAMPLE:
;
; X = [1, 2, 3]
; Y = [4, 5, 6, 7]
;
; ; Insert Y at the beginning of X
; result = arrinsert(x, y, at=0)
; --> result = [4, 5, 6, 7, 1, 2, 3]
;
; ; Insert Y in the middle of X
; result = arrinsert(x, y, at=1)
; --> result = [1, 4, 5, 6, 7, 2, 3]
;
; ; Append Y at the end of X
; result = arrinsert(x, y, at=-1)
; --> result = [1, 2, 3, 4, 5, 6, 7]
;
; SEE ALSO:
;
; ARRDELETE, STORE_ARRAY in IDL Astronomy Library
;
; MODIFICATION HISTORY:
; Written, CM, 02 Mar 2000
; Added OVERWRITE and EMPTY keywords, CM, 04 Mar 2000
; Improved internal docs, and AT keyword docs, CM, 28 Sep 2000
; Doc clarifications, CM, 29 Sep 2001
; Added examples to documentation, CM, 06 Apr 2008
;
; $Id: arrinsert.pro,v 1.4 2008/07/08 20:24:59 craigm Exp $
;
;-
; Copyright (C) 2000,2001,2008, Craig Markwardt
; This software is provided as is without any warranty whatsoever.
; Permission to use, copy, modify, and distribute modified or
; unmodified copies is granted, provided this copyright and disclaimer
; are included unchanged.
;-
function arrinsert, init, insert, at=at0, count=count, overwrite=overwrite, $
empty1=empty1, empty2=empty2
on_error, 2
;; Total number of elements in output
count = (n_elements(init)*(keyword_set(empty1) EQ 0) + $
n_elements(insert)*(keyword_set(empty2) EQ 0))
;; Account for various "empty" special cases.
;; INIT and INSERT are empty
if (n_elements(init) EQ 0 OR keyword_set(empty1)) AND $
(n_elements(insert) EQ 0 OR keyword_set(empty2)) then return, -1L
;; INIT alone is empty
if (n_elements(init) EQ 0 OR keyword_set(empty1)) then $
return, reform([insert], n_elements(insert))
;; INSERT alone is empty
if (n_elements(insert) EQ 0 OR keyword_set(empty2)) then $
return, reform([init], n_elements(init), overwrite=keyword_set(overwrite))
n1 = n_elements(init) & sz1 = size(init) & tp1 = sz1(sz1(0)+1)
n2 = n_elements(insert) & sz2 = size(insert) & tp2 = sz2(sz2(0)+1)
;; Compute insertion position using AT keyword
if n_elements(at0) EQ 0 then at = 0L else at = long(at0(0))
if at LT 0 then at = (n1 + 1L + at) > 0
at = (at > 0) < n1
;; Allow data to have different types, but they must be at least of
;; the same "base" type. That is, you can't combine a number with a
;; string, etc.
;; basetype 0:undefined 1:real number 6:complex number 7:string
;; 8:structure 10:pointer 11:object
;; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
basetype = [0, 1, 1, 1, 1, 1, 6, 7, 8, 6,10,11, 1, 1, 1, 1]
if tp1 LT 0 OR tp1 GE 16 OR tp2 LT 0 OR tp2 GE 16 then $
message, 'ERROR: unrecognized data types for operands'
if basetype(tp1) NE basetype(tp2) then $
message, 'ERROR: operands must have same data type'
if keyword_set(overwrite) then ct = n2 else ct = n1+n2
;; Create new output array
if tp1 EQ 8 then out = make_array(value=init(0), ct) $
else out = make_array(type=tp1, ct, /nozero)
if keyword_set(overwrite) then begin
;; Overwrite, so we try to conserve as much memory as possible,
;; and reduce the amount of copying
if at LT n1/2 then begin ;; Closer to begining
out = [temporary(out), temporary(init)]
if at GT 0 then out(0) = out(n2:at+n2-1)
endif else begin ;; Closer to end
out = [temporary(init), temporary(out)]
if at LT n1 then out(at+n2) = out(at:n1-1)
endelse
endif else begin
;; Otherwise, copy the old data into place
if at GT 0 then out(0) = init(0:at-1)
if at LT n1 then out(at+n2) = init(at:*)
endelse
;; Insert the new data
out(at) = reform([insert], n2)
return, out
end