math_ops.c

← Back to explorer
src/ math_ops.c
Raw
C 203 lines · UTF-8
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
#include "math_ops.h"
#include <stddef.h>
#include <string.h>
#include <math.h>

void compute_math_add(float *out, const float *term_a, const float *term_b, int total) {
  for (int i = 0; i < total; i++) {
    out[i] = term_a[i] + term_b[i];
  }
}

void compute_math_subtract(float *out, const float *term_a, const float *term_b, int total) {
  for (int i = 0; i < total; i++){
       out[i] = term_a[i] - term_b[i];
  }
}

void compute_math_scale(float *data, float scalar_term, int total) {
  for (int i = 0; i < total; i++) {
    data[i]  *= scalar_term;
  }
}

void compute_math_fill(float *data, float value, int total) {
  for (int i = 0; i < total; i++) {
    data[i] = value;
  }
}

void compute_math_clear(float *data, int total) {
  memset(data, 0, sizeof(float) * total);
}

void compute_math_copy(float *dest, const float *src, int total) {
  memcpy(dest, src, sizeof(float) * total);
}

void compute_math_accumulate(float *dest, const float *src, int total) {
  for (int i = 0; i < total; i++) {
    dest[i] += src[i];
  }
}

void compute_add_bias(float *out, const float *value, const float *bias, int rows, int columns) {
  for (int row = 0; row < rows; row++) {
    for (int column = 0; column < columns; column++) {
      out[row * columns + column] = value[row * columns + column] + bias[row];
    }
  }
}

void compute_add_bias_gradient(float *bias_gradient, const float *upstream_gradient, int rows, int columns) {
  for (int row = 0; row < rows; row++) {
    float sum = 0.0f;
    for (int column = 0; column < columns; column++) {
      sum += upstream_gradient[row * columns + column];
    }
    bias_gradient[row] += sum;
  }
}

void compute_math_matrix_multiplication_nn(float *out, const float *term_a, const float *term_b, int m, int n, int k, int zero_output) {
  if (zero_output) {
    memset(out, 0, sizeof(float) * m * n);
  }

  for (int row = 0; row < m; row++) {
    for(int inner_row = 0; inner_row < k; inner_row++) {
      for (int column = 0; column < n; column++) {
        out[row * n + column] += term_a[row * k + inner_row] * term_b[inner_row * n + column];
      }
    }
  }
}


void compute_math_matrix_multiplication_nt(float *out, const float *term_a, const float *term_b, int m, int n, int k, int zero_output) {
  if (zero_output) {
    memset(out, 0, sizeof(float) * m * n);
  }

  for (int row = 0; row < m; row++) {
    for(int inner_row = 0; inner_row < k; inner_row++) {
      for (int column = 0; column < n; column++) {
        out[row * n + column] += term_a[row * k + inner_row] * term_b[column * k + inner_row];
      }
    }
  }
}


void compute_math_matrix_multiplication_tn(float *out, const float *term_a, const float *term_b, int m, int n, int k, int zero_output) {
  if (zero_output) {
    memset(out, 0, sizeof(float) * m * n);
  }

  for (int inner_row = 0; inner_row < k; inner_row++) {
    for(int row = 0; row < m; row++) {
      for (int column = 0; column < n; column++) {
        out[row * n + column] += term_a[inner_row * m + row] * term_b[inner_row * n + column];
      }
    }
  }
}


void compute_math_matrix_multiplication_tt(float *out, const float *term_a, const float *term_b, int m, int n, int k, int zero_output) {
  if (zero_output) {
    memset(out, 0, sizeof(float) * m * n);
  }

  for (int row = 0; row < m; row++) {
    for(int column = 0; column < n; column++) {
      for (int inner_row = 0; inner_row < k; inner_row++) {
        out[row * n + column] += term_a[inner_row * m + row] * term_b[column * k + inner_row];
      }
    }
  }
}

void compute_relu_forward(float *out, const float *in, int total) {
  for (int i = 0; i < total; i++) {
    out[i] = in[i] > 0.0f ? in[i]: 0.0f;
  }
}

void compute_relu_backward(float *input_gradient, const float *in, const float *upstream_gradient, int total) {
  for (int i = 0; i < total; i++) {
    input_gradient[i] += (in[i] > 0.0f) ? upstream_gradient[i] : 0.0f;
  }
}

void compute_softmax_forward(float *out, const float *in, int rows, int columns) {
  for (int column = 0; column < columns; column++) {
    float max_value = in[column];
    for (int row = 1; row < rows; row++) {
      float v = in[row * columns + column];
      if (v > max_value) {
        max_value = v;
      }
    }

    float exponential_sum = 0.0f;
    for (int row = 0; row < rows; row++) {
      float e = expf(in[row * columns + column] - max_value);
      out[row * columns + column] = e;
      exponential_sum += e;
    }

    float inverse_sum = 1.0f / exponential_sum;
    for (int row = 0; row < rows; row++) {
      out[row * columns + column] *= inverse_sum;
    }
  }
}

void compute_softmax_backward(float *input_gradient, const float *softmax_out, const float *upstream_gradient, int rows, int columns) {
  for (int column = 0; column < columns; column++) {
    for (int i = 0; i < rows; i++) {
      float partial_sum = 0.0f;
      float si = softmax_out[i * columns + column];

      for (int j = 0; j < rows; j++) {
        float sj = softmax_out[j * columns + column];
        float jacobian_elem = (i == j) ? si * (1.0f - si) : -si * sj;
        partial_sum += jacobian_elem * upstream_gradient[j * columns + column];
      }

      input_gradient[i * columns + column] += partial_sum;
    }
  }
}

void compute_cross_entropy_forward(float *out, const float *predicted, const float *expected, int total) {
  for (int i = 0; i < total; i++) {
    if (expected[i] == 0.0f) {
      out[i] = 0.0f;
    } else {
      float clamped_data = predicted[i] > 1e-7f ? predicted[i] : 1e-7f;
      out[i] = -expected[i] * logf(clamped_data);
    }
  }
}

void compute_cross_entropy_predicted(float *predicted_gradient, const float *predicted_value, const float *expected_value, const float *upstream_gradient, int total) {
  for (int i = 0; i < total; i++) {
    float clamped_data = predicted_value[i] > 1e-7f ? predicted_value[i] : 1e-7f;
    predicted_gradient[i] += (-expected_value[i] / clamped_data) * upstream_gradient[i];
  }
}

void compute_cross_entropy_expected(float *expected_Gradient, const float *predicted_value, const float *upstream_gradient, int total) {
  for (int i = 0; i < total; i++) {
    float clamped_data = predicted_value[i] > 1e-7f ? predicted_value[i] : 1e-7f;
    expected_Gradient[i] += (-logf(clamped_data)) * upstream_gradient[i];
  }
}

void compute_param_update(float *parameter, const float *gradient, float scaled_learning_rate, int total) {
  for (int i = 0; i < total; i++) {
    parameter[i] -= scaled_learning_rate * gradient[i];
  }
}