// File: /workspace/github_cpp_makefile_star2_O2/tomfunkhouser[P]gaps/pkgs/R3Shapes/R3MeshPropertySet.cpp
// Function: gaps::R3MeshPropertySet::ReadNumpy(char const*)
int R3MeshPropertySet::
ReadNumpy(const char *filename)
{
  // Open file
  FILE *fp = fopen(filename, "rb");
  if (!fp) {
    fprintf(stderr, "Unable to open npy file %s\n", filename);
    return 0;
  }
  
  // Read magic string
  unsigned char magic[6];
  if (fread(magic, sizeof(unsigned char), 6, fp) != (unsigned int) 6) {
    fprintf(stderr, "Unable to read first character from npy file\n");
    fclose(fp);
    return 0;
  }

  // Check magic string
  if ((magic[0] != 0x93) || (magic[1] != 'N') || (magic[2] != 'U') ||
      (magic[3] != 'M')  || (magic[4] != 'P') || (magic[5] != 'Y')) {
    fprintf(stderr, "Unrecognized format in npy file\n");
    fclose(fp);
    return 0;
  }

  // Read version info
  unsigned char version[2];
  if (fread(version, sizeof(unsigned char), 2, fp) != (unsigned int) 2) {
    fprintf(stderr, "Unable to read version in npy file\n");
    fclose(fp);
    return 0;
  }
  
  // Read header length
  unsigned short int header_length;
  if (fread(&header_length, sizeof(unsigned short), 1, fp) != (unsigned int) 1) {
    fprintf(stderr, "Unable to read header length in npy file\n");
    fclose(fp);
    return 0;
  }

  // Check header length
  if (header_length <= 0) {
    fprintf(stderr, "Invalid header length in npy file\n");
    fclose(fp);
    return 0;
  }

  // Read header
  char *header = new char [ header_length + 1 ];
  if (fread(header, sizeof(char), header_length, fp) != (unsigned int) header_length) {
    fprintf(stderr, "Unable to read header in npy file\n");
    delete [] header;
    fclose(fp);
    return 0;
  }
  header[header_length] = '\0';

  // Extract data type and size
  int data_type = 0;
  int data_size = 0;
  char *start = strstr(header, "'descr'");
  if (start) {
    start = strchr(start, '<');
    if (start) {
      start++;
      while (*start == ' ') start++;
      data_type = *start;
      start++;
      char *end = strchr(start, '\'');
      if (end && (start < end)) {
        *end = '\0';
        data_size = atoi(start);
        *end = '\'';
      }
    }
  }

  // Extract fortrain order
  int fortran_order = 0;
  start = strstr(header, "'fortran_order'");
  if (start) {
    start = strchr(start, ':');
    if (start) {
      start++;
      while (*start == ' ') start++;
      char *end = strchr(start, ',');
      if (end && (start < end)) {
        *end = '\0';
        if (!strcmp(start, "True")) fortran_order = 1;
        if (!strcmp(start, "true")) fortran_order = 1;
        *end = ',';
      }
    }
  }

  // Extract width
  int width = 1;
  start = strstr(header, "'shape'");
  if (start) {
    start = strchr(start, '(');
    if (start) {
      start++;
      while (*start == ' ') start++;
      char *end = strchr(start, ',');
      if (end && (start < end)) {
        *end = '\0';
        width = atoi(start);
        *end = ',';
      }
    }
  }

  // Extract height
  int height = 1;
  start = strstr(header, "'shape'");
  if (start) {
    start = strchr(start, ',');
    if (start) {
      start++;
      while (*start == ' ') start++;
      char *end1 = strchr(start, ',');
      char *end2 = strchr(start, ')');
      char *end = (end1 < end2) ? end1 : end2;
      if (end && (start < end)) {
        *end = '\0';
        height = atoi(start);
        *end = ')';
      }
    }
  }

  // Delete header
  delete [] header;

  // Read values
  unsigned int nbytes = width * height * NumpyDataTypeSize(data_type, data_size);
  unsigned char *array = new unsigned char [ nbytes ];
  unsigned int read_nbytes = 0;
  while (read_nbytes < nbytes) {
    size_t k = fread(&array[read_nbytes], sizeof(unsigned char), nbytes - read_nbytes, fp);
    if (k <= 0) {
      fprintf(stderr, "Unable to read array in npy file (%lu %u %u)\n", k, read_nbytes, nbytes);
      if (k < 0) {
        delete [] array;
        fclose(fp);
        return 0;
      }
    }
    read_nbytes += k;
  }

  // Close file
  fclose(fp);

  // Create properties
  for (int j = 0; j < height; j++) {
    char property_name[128];
    sprintf(property_name, "P%d", j);
    Insert(new R3MeshProperty(mesh, property_name));
  }

  // Fill property values
  unsigned char *arrayp = array;
  if (fortran_order) {
    // Fortran order
    for (int j = 0; j < height; j++) {
      for (int i = 0; i < width; i++) {
        if (data_size == 4) {
          float *a = (float *) arrayp;
          Property(j)->SetVertexValue(i, (float) *a);
          arrayp += 4;
        }
        else if (data_size == 8) {
          double *a = (double *) arrayp;
          Property(j)->SetVertexValue(i, (float) *a);
          arrayp += 8;
        }
      }
    }
  }
  else {
    // C order
    for (int i = 0; i < width; i++) {
      for (int j = 0; j < height; j++) {
        if (data_size == 4) {
          float *a = (float *) arrayp;
          Property(j)->SetVertexValue(i, (float) *a);
          arrayp += 4;
        }
        else if (data_size == 8) {
          double *a = (double *) arrayp;
          Property(j)->SetVertexValue(i, (float) *a);
          arrayp += 8;
        }
      }
    }
  }

  // Delete array
  delete [] array;
  
  // Return success
  return 1;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xc8, %rsp
movq %rsi, %r14
movq %rdi, 0x38(%rsp)
leaq 0x87a94(%rip), %rsi     # 0xc9376
movq %r14, %rdi
callq 0x21a90
testq %rax, %rax
je 0x41d62
movq %rax, %r13
leaq 0x20(%rsp), %rdi
pushq $0x1
popq %rsi
pushq $0x6
popq %rdx
movq %rax, %rcx
callq 0x21e40
cmpq $0x6, %rax
jne 0x41d81
cmpl $0x4d554e93, 0x20(%rsp) # imm = 0x4D554E93
jne 0x41d96
cmpb $0x50, 0x24(%rsp)
jne 0x41d96
cmpb $0x59, 0x25(%rsp)
jne 0x41d96
leaq 0x36(%rsp), %rdi
pushq $0x1
popq %rsi
pushq $0x2
popq %rdx
movq %r13, %rcx
callq 0x21e40
cmpq $0x2, %rax
jne 0x41dab
leaq 0x1e(%rsp), %rdi
pushq $0x2
popq %rsi
pushq $0x1
popq %rdx
movq %r13, %rcx
callq 0x21e40
cmpq $0x1, %rax
jne 0x41dc0
movzwl 0x1e(%rsp), %ebx
testq %rbx, %rbx
je 0x41dd5
leaq 0x1(%rbx), %rdi
callq 0x21040
movq %rax, %rbp
pushq $0x1
popq %rsi
movq %rax, %rdi
movq %rbx, %rdx
movq %r13, %rcx
callq 0x21e40
cmpq %rbx, %rax
jne 0x41e0f
movb $0x0, (%rbp,%rbx)
leaq 0x896bc(%rip), %rsi     # 0xcb06d
movq %rbp, %rdi
callq 0x21170
xorl %ebx, %ebx
testq %rax, %rax
je 0x41a09
pushq $0x3c
popq %rsi
movq %rax, %rdi
callq 0x21310
testq %rax, %rax
je 0x41a09
movq %rax, %r14
incq %r14
movsbl (%r14), %r12d
incq %r14
cmpl $0x20, %r12d
je 0x419d6
pushq $0x27
popq %rsi
movq %r14, %rdi
callq 0x21310
cmpq %rax, %r14
jae 0x41a0c
movq %rax, %r15
movb $0x0, (%rax)
movq %r14, %rdi
callq 0x21ed0
movl %eax, %ebx
movb $0x27, (%r15)
jmp 0x41a0c
xorl %r12d, %r12d
leaq 0x89662(%rip), %rsi     # 0xcb075
movq %rbp, 0x10(%rsp)
movq %rbp, %rdi
callq 0x21170
movb $0x1, %bpl
testq %rax, %rax
movq %rbx, 0x28(%rsp)
je 0x41a96
pushq $0x3a
popq %rsi
movq %rax, %rdi
callq 0x21310
testq %rax, %rax
je 0x41a96
movq %rax, %r14
cmpb $0x20, 0x1(%r14)
leaq 0x1(%r14), %r14
je 0x41a40
pushq $0x2c
popq %rsi
movq %r14, %rdi
callq 0x21310
cmpq %rax, %r14
jae 0x41a96
movq %rax, %r15
movb $0x0, (%rax)
leaq 0x8961d(%rip), %rsi     # 0xcb085
movq %r14, %rdi
callq 0x21d10
testl %eax, %eax
setne %bl
leaq 0x8960e(%rip), %rsi     # 0xcb08a
movq %r14, %rdi
callq 0x21d10
testl %eax, %eax
setne %bpl
andb %bl, %bpl
movq 0x28(%rsp), %rbx
movb $0x2c, (%r15)
movb %bpl, 0x7(%rsp)
leaq 0x895ed(%rip), %rsi     # 0xcb08f
movq 0x10(%rsp), %rdi
callq 0x21170
pushq $0x1
popq %rbp
movl %ebp, 0x8(%rsp)
testq %rax, %rax
je 0x41b00
pushq $0x28
popq %rsi
movq %rax, %rdi
callq 0x21310
pushq $0x1
popq %rbp
testq %rax, %rax
je 0x41b00
movq %rax, %r14
cmpb $0x20, 0x1(%r14)
leaq 0x1(%r14), %r14
je 0x41ace
pushq $0x2c
popq %rsi
movq %r14, %rdi
callq 0x21310
pushq $0x1
popq %rbp
cmpq %rax, %r14
jae 0x41b00
movq %rax, %r15
movb $0x0, (%rax)
movq %r14, %rdi
callq 0x21ed0
movl %eax, %ebp
movb $0x2c, (%r15)
leaq 0x89588(%rip), %rsi     # 0xcb08f
movq 0x10(%rsp), %rdi
callq 0x21170
testq %rax, %rax
je 0x41b7e
pushq $0x2c
popq %rsi
movq %rax, %rdi
callq 0x21310
testq %rax, %rax
je 0x41b7e
movq %rax, %r14
movl %ebp, 0x30(%rsp)
movq %r13, %rbp
cmpb $0x20, 0x1(%r14)
leaq 0x1(%r14), %r14
je 0x41b30
pushq $0x2c
popq %rsi
movq %r14, %rdi
callq 0x21310
movq %rax, %r13
pushq $0x29
popq %rsi
movq %r14, %rdi
callq 0x21310
movq %rax, %r15
cmpq %rax, %r13
cmovbq %r13, %r15
cmpq %r15, %r14
movq %rbp, %r13
movl 0x30(%rsp), %ebp
jae 0x41b7e
movb $0x0, (%r15)
movq %r14, %rdi
callq 0x21ed0
movl %eax, 0x8(%rsp)
movb $0x29, (%r15)
movq 0x10(%rsp), %rdi
callq 0x21c00
leal (,%rbx,4), %eax
cmpl $0x55, %r12d
cmovnel %ebx, %eax
movl %ebp, %r15d
imull 0x8(%rsp), %r15d
imull %eax, %r15d
movq %r15, %rdi
callq 0x21040
movq %rax, 0x10(%rsp)
xorl %r12d, %r12d
movl %r15d, %edx
subl %r12d, %edx
jbe 0x41c09
movl %ebp, %r14d
movl %r12d, %edi
addq 0x10(%rsp), %rdi
pushq $0x1
popq %rsi
movq %r13, %rbp
movq %r13, %rcx
callq 0x21e40
movq %rax, %r13
testq %rax, %rax
je 0x41be7
addl %r13d, %r12d
movq %rbp, %r13
movl %r14d, %ebp
jmp 0x41bb3
movq 0xf23c2(%rip), %rax     # 0x133fb0
movq (%rax), %rdi
leaq 0x8949f(%rip), %rsi     # 0xcb097
xorl %edx, %edx
movl %r12d, %ecx
movl %r15d, %r8d
xorl %eax, %eax
callq 0x21d80
jmp 0x41bdc
movq %r13, %rdi
callq 0x218b0
xorl %eax, %eax
movl 0x8(%rsp), %ecx
testl %ecx, %ecx
cmovlel %eax, %ecx
movl %ecx, 0x8(%rsp)
movq 0x38(%rsp), %rax
leaq 0x8(%rax), %r14
leaq 0x40(%rsp), %r12
xorl %r13d, %r13d
cmpl %r13d, 0x8(%rsp)
je 0x41c7e
movq %r12, %rdi
leaq 0x89483(%rip), %rsi     # 0xcb0c5
movl %r13d, %edx
xorl %eax, %eax
callq 0x21130
movl $0x448, %edi            # imm = 0x448
callq 0x218c0
movq %rax, %r15
movq 0x38(%rsp), %rax
movq (%rax), %rsi
movq %r15, %rdi
movq %r12, %rdx
xorl %ecx, %ecx
callq 0x42ae4
movq %r14, %rdi
movq %r15, %rsi
callq 0x26aa0
incl %r13d
jmp 0x41c31
xorl %r15d, %r15d
testl %ebp, %ebp
cmovlel %r15d, %ebp
movl 0x8(%rsp), %eax
movq %rax, 0x8(%rsp)
cmpb $0x0, 0x7(%rsp)
je 0x41cf6
movq 0x10(%rsp), %r13
cmpl %ebp, %r15d
je 0x41d50
movl %ebp, %r12d
xorl %ebp, %ebp
cmpq %rbp, 0x8(%rsp)
je 0x41cee
cmpl $0x8, %ebx
je 0x41cc5
cmpl $0x4, %ebx
jne 0x41ce9
movss (%r13), %xmm0
pushq $0x4
jmp 0x41ccd
cvtsd2ss (%r13), %xmm0
pushq $0x8
popq %rbx
movq (%r14), %rax
movq (%rax,%rbp,8), %rdi
cvtss2sd %xmm0, %xmm0
movl %r15d, %esi
callq 0x44320
addq %rbx, %r13
movq 0x28(%rsp), %rbx
incq %rbp
jmp 0x41caa
incl %r15d
movl %r12d, %ebp
jmp 0x41c9c
movl %ebp, %r12d
xorl %r13d, %r13d
movq 0x10(%rsp), %rbp
cmpq 0x8(%rsp), %r13
je 0x41d50
xorl %r15d, %r15d
cmpl %r15d, %r12d
je 0x41d4b
cmpl $0x8, %ebx
je 0x41d23
cmpl $0x4, %ebx
jne 0x41d46
movss (%rbp), %xmm0
pushq $0x4
jmp 0x41d2a
cvtsd2ss (%rbp), %xmm0
pushq $0x8
popq %rbx
movq (%r14), %rax
movq (%rax,%r13,8), %rdi
cvtss2sd %xmm0, %xmm0
movl %r15d, %esi
callq 0x44320
addq %rbx, %rbp
movq 0x28(%rsp), %rbx
incl %r15d
jmp 0x41d0b
incq %r13
jmp 0x41d01
movq 0x10(%rsp), %rdi
callq 0x21c00
pushq $0x1
popq %rbx
jmp 0x41dfb
movq 0xf2247(%rip), %rax     # 0x133fb0
movq (%rax), %rdi
leaq 0x891fb(%rip), %rsi     # 0xcaf6e
xorl %ebx, %ebx
movq %r14, %rdx
xorl %eax, %eax
callq 0x21d80
jmp 0x41dfb
movq 0xf2228(%rip), %rax     # 0x133fb0
movq (%rax), %rcx
leaq 0x891f8(%rip), %rdi     # 0xcaf8a
pushq $0x2d
jmp 0x41de8
movq 0xf2213(%rip), %rax     # 0x133fb0
movq (%rax), %rcx
leaq 0x89211(%rip), %rdi     # 0xcafb8
pushq $0x20
jmp 0x41de8
movq 0xf21fe(%rip), %rax     # 0x133fb0
movq (%rax), %rcx
leaq 0x8921d(%rip), %rdi     # 0xcafd9
pushq $0x23
jmp 0x41de8
movq 0xf21e9(%rip), %rax     # 0x133fb0
movq (%rax), %rcx
leaq 0x8922c(%rip), %rdi     # 0xcaffd
pushq $0x29
jmp 0x41de8
movq 0xf21d4(%rip), %rax     # 0x133fb0
movq (%rax), %rcx
leaq 0x89241(%rip), %rdi     # 0xcb027
pushq $0x22
popq %rsi
pushq $0x1
popq %rdx
callq 0x22290
movq %r13, %rdi
callq 0x218b0
xorl %ebx, %ebx
movl %ebx, %eax
addq $0xc8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0xf219a(%rip), %rax     # 0x133fb0
movq (%rax), %rcx
leaq 0x8922a(%rip), %rdi     # 0xcb04a
pushq $0x22
popq %rsi
pushq $0x1
popq %rdx
callq 0x22290
movq %rbp, %rdi
callq 0x21c00
jmp 0x41df1
movq %rax, %rbx
movl $0x448, %esi            # imm = 0x448
movq %r15, %rdi
callq 0x218e0
movq %rbx, %rdi
callq 0x220c0
nop