;+ ; ;Function: is_equal ; ;Purpose: determines if two inputs are equal ; like array_equal, but inputs can be structs ; Will descend structs within structs recursive ; Requires names of fields within structs to be the same ; ; Does not descend pointers to verify targets, if two ; different pointers have the same destination, it will return ; false. This may cause some problems, but it also prevents any infinite ; looping that can occur with pointer objects. (Future versions should fix this) ; ; Will not work on objects.It will always return false. (It should be made to) ; ; This is designed to be similar to the equal operation in LISP or Scheme. A ; high level equivalency operator that will test without halting regardless of input type. ; ; Does allow ambiguity between 0 element array and one element array ; ; ;Inputs: a,b: can be anything ; ;Outputs: 1:yes 0:no ; ;Keywords: array_strict: set this if you don't want it to allow conflation of 0 dimensional types and 1 element arrays ; ; ;NOTES: ; Right now this routine has only been tested to demonstrate its adequacy for use with the mini_language, ; It should be used with other routines with caution. If it ever reaches general purpose maturity, it will ; be placed in a different ssl_general directory. ; ;TODO: 1. Pointer & Object support needs to be added ; 2. Also struct tag strictness needs supported ; ; $LASTCHANGEDBY: DAVIN-WIN $ ; $LASTCHANGEDDATE: 2007-10-22 07:26:16 -0700 (MON, 22 OCT 2007) $ ; $LASTCHANGEDREVISION: 1758 $ ; $URL: svn+ssh://thmsvn@ambrosia.ssl.berkeley.edu/repos/spdsoft/tags/spedas_1_00/general/mini/is_equal.pro $ ;- function struct_equal,a,b,array_strict=array_strict,nan=nan compile_opt hidden,idl2 if ~keyword_set(array_strict) then begin at = [a] bt = [b] endif else begin at = a bt = b endelse if ~is_struct(at) || ~is_struct(bt) then begin return,0 endif a_tags = tag_names(at) b_tags = tag_names(bt) if ~array_equal(a_tags,b_tags) then begin return,0 endif for i = 0,n_elements(a_tags)-1L do begin if ~array_equal(size(at.(i)),size(bt.(i))) then begin return,0 endif if ~is_equal(at.(i),bt.(i),nan=nan) then begin return,0 endif endfor return,1 end function is_equal,a,b,array_strict=array_strict,nan=nan compile_opt idl2 if n_elements(a) eq 0 && n_elements(b) eq 0 then return, 1 if n_elements(a) eq 0 || n_elements(b) eq 0 then return, 0 if ~keyword_set(array_strict) then begin at = [a] bt = [b] endif else begin at = [a] bt = [b] endelse if ~array_equal(size(at),size(bt)) then return,0 ; if ~keyword_set(a) && ~keyword_set(b) then begin ; ; if n_elements(a) ne 0 then begin ; if ~keyword_set(array_strict) then begin ; at = [a] ; endif else begin ; at = a ; endelse ; endif ; ; if n_elements(b) ne 0 then begin ; if ~keyword_set(array_strict) then begin ; bt = [b] ; endif else begin ; bt = b ; endelse ; endif ; ; if array_equal(size(at),size(bt)) then begin ;ambiguity here, keyword_set returns 0 for undefined variables or for '' or 0 ; return,1 ; endif else begin ; return,0 ; endelse ; ; endif else if ~keyword_set(a) || ~keyword_set(b) then begin ; return,0 ; endif if is_struct(at) then begin ;only need to check one, already verified that are same type return,struct_equal(at,bt,nan=nan) endif else begin if keyword_set(nan) then begin ;check equivalency of nans ;positive nan idx_a = where(finite(at,/nan,sign=1),a_cnt) idx_b = where(finite(bt,/nan,sign=1),b_cnt) if a_cnt ne b_cnt then return,0 if a_cnt gt 0 && ~array_equal(idx_a,idx_b) then return,0 ;negative nan idx_a = where(finite(at,/nan,sign=-1),a_cnt) idx_b = where(finite(bt,/nan,sign=-1),b_cnt) if a_cnt ne b_cnt then return,0 if a_cnt gt 0 && ~array_equal(idx_a,idx_b) then return,0 ;not nan idx_a = where(~finite(at,/nan),a_cnt) idx_b = where(~finite(bt,/nan),b_cnt) if a_cnt ne b_cnt then return,0 if a_cnt gt 0 then begin return,array_equal(at[idx_a],bt[idx_b]) endif endif else begin return,array_equal(at,bt) endelse endelse end