"""
Numpy's mian object is the homogenoues multidimensional array.
It has an associated fast math function that operates on it.
It also provides simple routines for linear algebra and fft and
sophisticated random-number generation


Consider the numpy arrays like matrices with rows and columns
"""

import numpy as np #this is the most used way of importing numpy

#to can create a numpy array by using the array() keyword ,
#simillar to implicit conversion ie: int() ,str() in python

numpy_array = np.array([1,2,3,4,5])
#this is a multi dimentional array with single row


#to create multiple row and columns we have to use array( [ [ this is the element of the 1st row] ] ) *two sets of [ ] brackets
numpy_array_multidimensional = np.array([[1,2,4,5,5],[1,2,3,4,5],[5,10,14,20,25]])

#the shape of the array can be understood by the shape attribute

numpy_array_multidimensional.shape 
#returs (3,5) three rows (three sets of data), with 5 columns (with 5 data in each set)

#there is a function transpose , which can be used to take the transpose of the array 

numpy_array_multidimensional.transpose()



#arrage function returns a list of numbers from 0 --> n-1 
#which is similar to range(n) and stores it in a list

random_number_list  = np.arange(25) 

#reshape takes the single row list , generated by the arange function and
#turns it into m no.of lists with n no.of elements in each
#somewhat  like a matrix
random_number_list.reshape(5,3) 

#this can also be done in single line as 
single_line_random_number_list = np.arange(25).reshape(5,3)


#you can also use reshape with the previous array we generated

numpy_array_multidimensional =  numpy_array_multidimensional.reshape(5,3)

#we have some basic arithmatic operations which is used with matrices also 
#like marix multiplication

multiplied_array = numpy_array_multidimensional.dot(random_number_list.reshape(5,3))

#remember two matrices can only be multipled when their order is 
# m x n and n x p  so we reshaped the above matrix

#you can also add two arrays 
array_one = np.arange(10).reshape(2,5)
array_two = np.array([43,5,2,84,8,1,6,74,32,74]).reshape(2,5)

array_three = array_one + array_two 
#inorder to add two arrays their order must be same 

#there are some trigonomertic functions available in numpy
array_one_sin = np.sin(array_one)
#this converts all the elements of the array_one into their respective sin values
array_two_cos = np.cos(array_two)
#simlar to the previous , this time into cos

#you can peform simple arithmatic operations on the array , which affects all the elements

array_one_half = array_one/2 
array_one_power = array_one**2

#you know the all time simple trigo eqn sin(x)^2 + cos(x)^2 = 1
sum_of_sqrs = array_one_sin**2 + array_two_cos**2 



#you can create an array with all zeros using 
null_array_float = np.zeros(10)
#this will create a sinlge row array with all elements as zeroes, 
#as default the array elements are of float type , inorder to chanege the datatype , we give the value to dtype
null_array_int = np.zeros(5, dtype=int)
identity_array_int = np.ones(5, dtype=int)
identity_array_int_shaped = np.ones((8,5), dtype=int)

#there are many more functions available within numpy like 

array_one.sum()
#will return all the sums of the elements in an array

array_one.min()
#will will return the mininum value in the entire array , similarly there is .max() also


